Unit testing in GPFJS

Importing test files

New test files must be imported in gpfjs/src/test-files.ts like this:

import './app/[Component Name].spec.ts';

Warning

The test runner won’t see and won’t run files that are not imported!

Note

Changing which tests to be ran can be done with fdescribe and xdescribe. Doing that by editting the test files imports is bad practice.

Understanding test file structure

import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { Component } from './categorical-filter.component';

// Component test suite
// Contains test setup (test bed creation and others) and tests
describe('Component', () => {
    // The component can be interacted just like an object
    let component: Component;
    // Fixture - wrapper for a component and its template
    let fixture: ComponentFixture<Component>;

    beforeEach(waitForAsync(() => {
        // TestBed - mock environment for running component tests without browser
        // The most used parameters when configuring the testing module are the declarations, providers and imports
        TestBed.configureTestingModule({
            declarations: [
                // Declare components, directives, pipes that belong to the current module
                // so that they can interact with each other
            ],
            providers: [
                // Services that are expected to be used, will be injected to everything
                // that has them as a dependecy
            ],
            imports: [
                // External supporting modules needed
            ]
        })
        .compileComponents();
    }));

    // Create a new fixture before every test
    beforeEach(() => {
        // Create fixture from the configured environment
        fixture = TestBed.createComponent(CategoricalFilterComponent);
        // Getting an instance of the component
        component = fixture.componentInstance;
        fixture.detectChanges();
    });

    // Every test must be created inside an "it" block
    // The most basic test - check if the component is created
    it('should create', () => {
        expect(component).toBeTruthy();
    });
});

Warning

Configuring the testing module can be confusing, but do not skip it because incorrect configuration can lead to false positive tests!

Mocking dependencies

Replacing dependecy with a custom created mock:

class ImportantServiceMock {
    // Mocked body
}

describe('AutismGeneProfileSingleViewWrapperComponent', () => {
    const importantServiceMock = new ImportantServiceMock();

    beforeEach(waitForAsync(() => {
        TestBed.configureTestingModule({
            declarations: [],
            providers: [
                {provide: ImportantService, useValue: importantServiceMock},
            ],
            imports: []
        })
        .compileComponents();
    }));

Difference between “toBe” and “toEqual” equality matchers

Use “toBe” when you want to check strict equality and use “toEqual” when you seek deep equality, which is done by recursively searching and checking the insides of the provided variables.

Note

For primitive types, there is no difference between “toBe” and “toEqual”.