Angular Unit Test - Tuong-Nguyen/Angular-D3-Cometd GitHub Wiki

Continuous testing

Angular-cli application runs unit test with command npm test
This is continuous testing, ie: file update -> tests are run again.

Test file are suffix with spec.ts and are generated automatically by Generator.

Angular Test Bed (ATB)

Configuration

import { TestBed } from '@angular/core/testing';
describe('Login component', () => {

  // Configuration
  beforeEach(() => TestBed.configureTestingModule({
    declarations: [LoginComponent],
    providers: [RaceService]
  }));
});

Instantiate component & Resolve dependency

import { TestBed } from '@angular/core/testing';
describe('Component: Login', () => {

  // Configure providers
  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [LoginComponent],
      providers: [RaceService]
    }));

    // create component and test fixture
    fixture = TestBed.createComponent(LoginComponent);

    // get test component from the fixture
    component = fixture.componentInstance; 
    
    // AuthService provided to the TestBed
    authService = TestBed.get(AuthService);
  }
});
  • fixture is a wrapper for a component and its template
  • component = fixture.componentInstance
  • Resolve dependency with TestBed.get

Usage: - Specify mock dependencies.

Change detection

    // create component and test fixture
    fixture = TestBed.createComponent(LoginComponent);

    // get test component from the fixture
    component = fixture.componentInstance; 

    // query the wrapper DebugElement of <a> element
    el = fixture.debugElement.query(By.css('a'));
    
    // Update View
    fixture.detectChanges();

    // Get the DOM element of <a>
    expect(el.nativeElement.textContent.trim()).toBe('');
  }
});
  • DebugElement: wrapper to the low level DOM element that represents the components view
  • By: By.css, By.directive - query functions
  • fixture.detectChanges: update view according to state.
  • nativeElement: DOM object

Note: Life cycle hooks (ngOnInit, ...) must be called explicitly in test. Angular TestBed does not call them. The first call of fixture.detectChanges() also calls ngOnInit. Therefore, one practice is to call fixture.detectChanges right after creating the component in beforeEach.

Asynchronous testing

Async method and whenStable

it('Button label via async() and whenStable()', async(() => { 
  spyOn(authService, 'isAuthenticated').and.returnValue(Promise.resolve(true));

  component.ngOnInit();

  fixture.whenStable().then(() => { 
    fixture.detectChanges();
    expect(el.nativeElement.textContent.trim()).toBe('Logout');
  });
}));
  • Mock authService.isAuthenticated: return an Promise
  • whenStable() return a promis.

async use zones for keeping track all timeouts, listeners, callbacks ... It helps to not complete until all asynchronous actions are done. Only when all of those pending promises have been resolved does it then resolves the promise returned from whenStable.

fakeAsync and tick

it('Button label via fakeAsync() and tick()', fakeAsync(() => { 
  spyOn(authService, 'isAuthenticated').and.returnValue(Promise.resolve(true));

  component.ngOnInit();

  tick(); 
  fixture.detectChanges();
  expect(el.nativeElement.textContent.trim()).toBe('Logout');
}));

fakeAsync executes code in fake async test zone. tick() blocks execution and wait until asynchronous activities complete.

Note: fakeAsync has drawbacks; ex: cannot track XHR requests.

Nested component testing

Problem

Testing component depends on other components and its service that we don't want to test

Solution

  • Declare what we want to test and its directly dependencies
  • Tells the compiler not to error on unknown elements and attributes
TestBed.configureTestingModule({
      // ...
      schemas: [NO_ERRORS_SCHEMA]
    })

Unit Test Guidelines

Component

@Input

  • Verify basic appearance
  • Test UI Logic.

@Output

  • Check event is notified with correct argument after an action.

Form

Field validity

Field errors

Form validity

Form submission

Unit Test - Codecraft
Testing - Angular