Angular testing how to prevent ngOnInit call to test a method directly

前端 未结 3 1773
天命终不由人
天命终不由人 2020-12-24 02:35

Context

I have a component. Inside of it, the ngOnInit function calls another function of component to retrieve user List. I want to make two series of tets:

3条回答
  •  -上瘾入骨i
    2020-12-24 03:07

    Preventing lifecycle hook (ngOnInit) from being called is a wrong direction. The problem has two possible causes. Either the test isn't isolated enough, or testing strategy is wrong.

    Angular guide is quite specific and opinionated on test isolation:

    However, it's often more productive to explore the inner logic of application classes with isolated unit tests that don't depend upon Angular. Such tests are often smaller and easier to read, write, and maintain.

    So isolated tests just should instantiate a class and test its methods

    userManagementService = new UserManagementServiceStub;
    comp = new UserListComponent(userManagementService);
    spyOn(comp, 'getUserList');
    
    ...
    comp.ngOnInit();
    expect(comp.getUserList).toHaveBeenCalled();
    
    ...
    comp.onRefreshUserList();
    expect(comp.getUserList).toHaveBeenCalled();
    

    Isolated tests have a shortcoming - they don't test DI, while TestBed tests do. Depending on the point of view and testing strategy, isolated tests can be considered unit tests, and TestBed tests can be considered functional tests. And a good test suite can contain both.

    In the code above should get the user List via refresh function test is obviously a functional test, it treats component instance as a blackbox.

    A couple of TestBed unit tests can be added to fill the gap, they probably will be solid enough to not bother with isolated tests (although the latter are surely more precise):

    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);
    

提交回复
热议问题