Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/heroku/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular 角度测试如何防止ngOnInit调用直接测试方法 上下文_Angular_Typescript_Jasmine_Karma Jasmine - Fatal编程技术网

Angular 角度测试如何防止ngOnInit调用直接测试方法 上下文

Angular 角度测试如何防止ngOnInit调用直接测试方法 上下文,angular,typescript,jasmine,karma-jasmine,Angular,Typescript,Jasmine,Karma Jasmine,我有一个组件。在它内部,ngOnInit函数调用组件的另一个函数来检索用户列表。我想制作两个系列的TET: 首先测试Ngonit是否正确触发并填充用户列表 第二次,我想测试我的刷新函数,它也调用getUserList() 当我调用fixture.detectChanges()时,第一个测试是使用ngOnInit触发器进行的 问题 我的问题是在测试refresh函数时:只要我调用fixture.detectChanges(),就会触发ngOnInit,然后我就无法知道我的结果来自何处,也无法知

我有一个组件。在它内部,ngOnInit函数调用组件的另一个函数来检索用户列表。我想制作两个系列的TET:

  • 首先测试Ngonit是否正确触发并填充用户列表
  • 第二次,我想测试我的刷新函数,它也调用getUserList()
当我调用fixture.detectChanges()时,第一个测试是使用ngOnInit触发器进行的

问题 我的问题是在测试refresh函数时:只要我调用fixture.detectChanges(),就会触发ngOnInit,然后我就无法知道我的结果来自何处,也无法知道我的refresh()函数是否会被正确测试

在我对
refresh()
方法进行第二系列测试之前,有没有办法“删除”或“阻止”
ngOnInit()
,这样就不会在
fixture.detectChanges()上调用它?

我试图查看
overrideComponent
,但它似乎不允许删除
ngOnInit()

或者在我的情况下,除了使用
fixture.detectChanges
之外,还有其他方法检测更改吗?

代码 下面是组件、存根服务和我的规范文件的代码

组成部分 元件规格文件 我的审判 我尝试了一些“变通方法”,但我发现有点。。。。长篇大论,也许是矫枉过正

例如:

it(`should get the user List via refresh function`, fakeAsync(() => {
    expect(comp.userList.length).toBe(0, 'user list must be empty');

    // Here ngOnInit is called, so I override the result from onInit
    fixture.detectChanges();
    expect(comp.userList.length).toBe(3, 'ngOnInit');

    comp.userList = [];
    fixture.detectChanges();
    expect(comp.userList.length).toBe(0, 'ngOnInit');

    // Then call the refresh function
    comp.onRefreshUserList(true);
    tick();
    fixture.detectChanges();

    expect(comp.userList.length).toBe(3, 'user list after function call');
}));

防止调用生命周期挂钩(
ngOnInit
)是一个错误的方向。这个问题有两个可能的原因。要么测试不够孤立,要么测试策略错误

角导轨相当:

但是,使用独立的单元测试来探索应用程序类的内部逻辑通常会更有效,因为这些单元测试不依赖于角度。此类测试通常更小,更易于阅读、编写和维护

所以独立测试应该实例化一个类并测试它的方法

userManagementService = new UserManagementServiceStub;
comp = new UserListComponent(userManagementService);
spyOn(comp, 'getUserList');

...
comp.ngOnInit();
expect(comp.getUserList).toHaveBeenCalled();

...
comp.onRefreshUserList();
expect(comp.getUserList).toHaveBeenCalled();
独立测试有一个缺点——它们不测试DI,而测试台测试则测试DI。根据观点和测试策略,独立测试可以被视为单元测试,而测试台测试可以被视为功能测试。一个好的测试套件可以同时包含这两者

在上面的代码中,
应该通过刷新函数获取用户列表
测试显然是一个功能测试,它将组件实例视为黑盒

可以添加两个测试台单元测试来填补这一空白,它们可能足够可靠,不需要进行单独的测试(尽管后者肯定更精确):


我个人更喜欢在每次测试中取消组件

beforeEach(() => {
    UserListComponent.prototype.ngOnInit = () => {} ;
   ....
  });

你不能阻止Ngonit,因为当你创建一个组件实例时,它就被触发了,你需要创建一个组件实例来编写测试用例。最好有一个更可控的存根;这样,您就可以控制每次调用它时返回的数据,这样您就知道第二次调用时数据应该是不同的。您可以使用
主题
来为订阅者推送新数据,可以本地推送,也可以在存根上使用其他测试方法,或者监视方法
。和.returnValue
随您喜欢。我对spy很不舒服,但在我的两个系列测试中插入不同的returnValue似乎是一个很好的解决方案,也许先把间谍分为两类。你有没有关于如何做到这一点的例子?
it(`should get the user List via refresh function`, fakeAsync(() => {
    expect(comp.userList.length).toBe(0, 'user list must be empty');

    // Here ngOnInit is called, so I override the result from onInit
    fixture.detectChanges();
    expect(comp.userList.length).toBe(3, 'ngOnInit');

    comp.userList = [];
    fixture.detectChanges();
    expect(comp.userList.length).toBe(0, 'ngOnInit');

    // Then call the refresh function
    comp.onRefreshUserList(true);
    tick();
    fixture.detectChanges();

    expect(comp.userList.length).toBe(3, 'user list after function call');
}));
it(`should get the user List via refresh function`, fakeAsync(() => {
  let ngOnInitFn = UserListComponent.prototype.ngOnInit;
  UserListComponent.prototype.ngOnInit = () => {} // override ngOnInit
  comp.onRefreshUserList();
  tick();

  fixture.detectChanges(); 
  UserListComponent.prototype.ngOnInit = ngOnInitFn; // revert ngOnInit

  expect(comp.userList.length).toBe(3, 'user list after function call');
}));
userManagementService = new UserManagementServiceStub;
comp = new UserListComponent(userManagementService);
spyOn(comp, 'getUserList');

...
comp.ngOnInit();
expect(comp.getUserList).toHaveBeenCalled();

...
comp.onRefreshUserList();
expect(comp.getUserList).toHaveBeenCalled();
spyOn(comp, 'getUserList');

comp.onRefreshUserList();
expect(comp.getUserList).toHaveBeenCalledTimes(1);

...

spyOn(comp, 'getUserList');
spyOn(comp, 'ngOnInit').and.callThrough();

tick();
fixture.detectChanges(); 

expect(comp.ngOnInit).toHaveBeenCalled();
expect(comp.getUserList).toHaveBeenCalledTimes(1);
beforeEach(() => {
    UserListComponent.prototype.ngOnInit = () => {} ;
   ....
  });