Angular5 Materialized Design And Karma Unit Tests Cheat Sheet

· Read in about 2 min · (267 words) ·

Running tests

  • Run command from Angular5 project folder: ng test

Create an injectable service with an interface

  • This allows to define a typescript interface implemented by a class
  • For injection is actually used the AUTHENTICATION_SERVICE token
import { Injectable, InjectionToken } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';

export interface IAuthenticationService {
    login(username: string, password: string): Observable<any>;
    extendToken(): Observable<any>;
    logout();
    isLoggedIn(): boolean;
    hasRole(role: string): boolean;
}

export const AUTHENTICATION_SERVICE = new InjectionToken<IAuthenticationService>('AUTHENTICATION_SERVICE');

@Injectable()
export class AuthenticationService implements IAuthenticationService {
    constructor(private http: HttpClient) { }

    // returns actually the token
    login(username: string, password: string): Observable<any> {
        return this.http.post<any>('api/sign-in', { username: username, password: password })
            .map(token => {
                this.updateToken(token);
                return token;
            });
    }
}
  • Injecting the dependency utilizing interface IAuthenticationService and injection token AUTHENTICATION_SERVICE
constructor(
    @Inject(AUTHENTICATION_SERVICE) private authenticationService: IAuthenticationService) { }

Creating a spy object/mock

...

describe('AppComponent', () => {
  let serviceSpy: jasmine.SpyObj<IMyService>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [
        AppComponent
      ],
      providers: [
        {
          provide: MY_SERVICE,
          useValue: jasmine.createSpyObj('IMyService', ['isLoggedIn', 'hasRole'])
        }
      ],
      imports: [HttpClientTestingModule]
    }).compileComponents();
  }));

  beforeEach(() => {
    serviceSpy = TestBed.get(MY_SERVICE);
    // preconfigure expected return value
    serviceSpy.hasRole = jasmine.createSpy().and.returnValue(false);
  });

...

Validating passed parameters on spy/mock

expect(serviceSpy.hasRole).toHaveBeenCalledWith('admin');

Setting returned value from a spy/mock method

serviceSpy.hasRole = jasmine.createSpy().and.returnValue(false);

Mocking router related stuff

  • Needs to include module RouterTestingModule

Mocking ActivatedRoute and Router

import { ActivatedRoute, Router, convertToParamMap } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';

...

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ LicenseEventLogComponent ],
      providers: [
        {
          provide: ActivatedRoute,
          useValue: {
            snapshot: {
              paramMap: convertToParamMap({ id: '123' })
            }
          }
        },
        {
          provide: Router,
          useValue: jasmine.createSpyObj('Router', ['navigate'])
        },

...