Slide 1

Slide 1 text

Angular Unit Testing with Jest Christian Liebel @christianliebel Consultant

Slide 2

Slide 2 text

Angular Unit Testing DEMO: Motivation

Slide 3

Slide 3 text

1. Testing Overview 2. Unit Testing Basics 3. Jest vs. Karma/Jasmine 4. Testing with Jest 5. Spies & Mocks 6. E2E Tests Overview Angular Unit Testing Agenda O

Slide 4

Slide 4 text

Test Types End-to-end Tests (~ 1000 ms, 10%) Acceptance tests simulating a real user Integration Tests (~ 100 ms, 20%) Tests the integration of different modules Unit Tests (~ 10 ms, 70 %) Tests a class, method or algorithm Angular Unit Testing Testing Overview

Slide 5

Slide 5 text

Test-Driven Development First, write your test (= requirements!) See it failing Next, write the minimum required implementation to fulfill the test See your test turn green (Refactor) Repeat Angular Unit Testing Unit Testing Basics

Slide 6

Slide 6 text

Brownfield Testing Use Extract Method refactoring to… - reduce complexity of large methods (target method length: 7±2 lines) - avoid more than one nesting/indent level Move large blocks of code in own files or services (target file length: ±100 lines) Angular Unit Testing Unit Testing Basics

Slide 7

Slide 7 text

A-TRIP Pattern Unit Tests should be… - Automatic (no user interaction required) - Thorough (test critical functionality) - Repeatable (repeated execution leads to same result) - Independent (order does not matter) - Professional (test code doesn’t test itself) Angular Unit Testing Unit Testing Basics

Slide 8

Slide 8 text

Unit Testing Support Unit Tests (~ 10 ms, 70 %) Tests a class, method or algorithm Integration Tests (~ 100 ms, 20%) Tests the integration of different modules End-to-end Tests (~ 1000 ms, 10%) Acceptance tests simulating a real user Angular Unit Testing Angular

Slide 9

Slide 9 text

Unit Testing Support Angular CLI schematics automatically create a test specification file (*.spec.ts) for each generated unit. Angular Unit Testing Angular

Slide 10

Slide 10 text

Angular’s Default Testing System - Does not require additional project configuration - Requires a browser (e.g. Chrome Headless for CI environments) - Tests run sequentially Angular Unit Testing Karma & Jasmine

Slide 11

Slide 11 text

Test runner Angular Unit Testing Jest - Fast: Tests run in parallel - Easy CI setup: No browser required (JSDom) - Setup: ng add @briebug/jest-schematic - Jasmine BDD testing framework is mostly compatible with Jest - Migration: npx jest-codemods P

Slide 12

Slide 12 text

Introduction https://jestjs.io/docs/en/getting-started Angular Unit Testing Jest

Slide 13

Slide 13 text

Simple Test describe("A suite is just a function", () => { let a; test("and so is a spec", () => { a = true; expect(a).toBe(true); }); }); Angular Unit Testing Jest

Slide 14

Slide 14 text

AAA Pattern Arrange const x = …; Act const result = sut.myTestMethod(x); Assert expect(result).toBeDefined(); Angular Unit Testing Unit Tests

Slide 15

Slide 15 text

Matchers expect(123).toBe(123); expect({ foo: 123 }).toEqual({ foo: 123 }); expect([1, 2, 3]).toContain(3); expect(false).toBeFalsy(); expect(1).toBeTruthy(); expect(null).toBeNull(); expect(undefined).toBeUndefined(); expect(999).toBeDefined(); expect(() => method()).toThrow(); Angular Unit Testing Jest

Slide 16

Slide 16 text

Suggestion describe('FooService', () => { describe('method', () => { test('should do this', () => {}); test('should do that', () => {}); }); }); - 1 suite per class - 1 suite per method - n tests (use “should” and prevent “and”) Angular Unit Testing Jest

Slide 17

Slide 17 text

Setup/Teardown Run before/after each test in this suite beforeEach afterEach Run before/after all tests in this suite beforeAll afterAll Angular Unit Testing Jest

Slide 18

Slide 18 text

Excluding/including tests Exclude this test (suite) describe.skip test.skip Only include this test (suite) describe.only test.only Angular Unit Testing Jest

Slide 19

Slide 19 text

Test Reminders Remind me to write a test test.todo Angular Unit Testing Jest

Slide 20

Slide 20 text

Unit Testing Commands Unit Tests (Karma/Jest) npm test ng test ng t End-to-end Tests ng e2e ng e Angular Unit Testing Angular

Slide 21

Slide 21 text

Angular Unit Testing DEMO: Testing Angular Pipes

Slide 22

Slide 22 text

Repetitive tests test.each` a | b | expected ${1} | ${1} | ${2} ${1} | ${2} | ${3} ${2} | ${1} | ${3} `('returns $expected when $a is added $b', ({a, b, expected}) => { expect(a + b).toBe(expected); }); Angular Unit Testing Jest https://jestjs.io/docs/en/api#testeachtablename-fn-timeout

Slide 23

Slide 23 text

Mock Functions const mock = jest.fn(x => 42 + x); // The mock function is called twice expect(mockCallback.mock.calls.length).toBe(2); // The first argument of the second call to the function was 1 expect(mockCallback.mock.calls[1][0]).toBe(1); Angular Unit Testing Jest https://jestjs.io/docs/en/mock-functions

Slide 24

Slide 24 text

Spies jest.spyOn(existingObject, 'existingFunction'); // spyOn also calls the function, alternatives: // jest.spyOn(/* … */).mockImplementation(() => 42); // existingObject['existingFunction'] = jest.fn(() => 42); expect(existingObject.existingFunction).toHaveBeenCalled(); // optional: toHaveBeenCalledWith(arg1, arg2) // optional: toHaveBeenCalledTimes(4) Angular Unit Testing Jest

Slide 25

Slide 25 text

Basics // Creating mock let mockedFoo:Foo = mock(Foo); // Getting instance from mock let foo:Foo = instance(mockedFoo); // Using instance in source code foo.getBar(5); // Explicit, readable verification verify(mockedFoo.getBar(5)).called(); Angular Unit Testing ts-mockito https://www.npmjs.com/package/ts-mockito

Slide 26

Slide 26 text

Stubbing Method Calls // Creating mock let mockedFoo:Foo = mock(Foo); // stub method before execution when(mockedFoo.getBar(3)).thenReturn('three'); // Getting instance let foo:Foo = instance(mockedFoo); // prints three console.log(foo.getBar(3)); Angular Unit Testing ts-mockito https://www.npmjs.com/package/ts-mockito

Slide 27

Slide 27 text

AAA Pattern & Mocks Arrange const x = …; Setup when(mock.myOtherMethod).thenReturn(3); Act const result = sut.myTestMethod(x); Assert expect(result).toBeDefined(); Verify verify(mock.myOtherMethod).called(); Angular Unit Testing Unit Tests

Slide 28

Slide 28 text

Angular Unit Testing DEMO: Mocking Dependencies O

Slide 29

Slide 29 text

Testing Utilities: TestBed describe('Component: Login', () => { beforeEach(() => { TestBed.configureTestingModule({ declarations: [LoginComponent], providers: [AuthService] }); }); }); Angular Unit Testing Angular https://codecraft.tv/courses/angular/unit-testing/angular-test-bed/

Slide 30

Slide 30 text

Angular Unit Testing DEMO: Using the TestBed

Slide 31

Slide 31 text

Snapshot Testing test('should create the app', () => { const fixture = TestBed.createComponent(AppComponent); expect(fixture).toMatchSnapshot(); }); Angular Unit Testing Jest

Hallo

Hxllo

Slide 32

Slide 32 text

Angular Unit Testing DEMO: Snapshot Testing

Slide 33

Slide 33 text

Test Harnesses test('should mark confirmed when ok button clicked', async () => { const okButton = await loader.getHarness(MatButtonHarness.with({selector: '.confirm'}); expect(fixture.componentInstance.confirmed).toBe(false); expect(await okButton.isDisabled()).toBe(false); await okButton.click(); expect(fixture.componentInstance.confirmed).toBe(true); }); https://material.angular.io/guide/using-component-harnesses Angular Unit Testing Angular

Slide 34

Slide 34 text

Testing Utilities: fakeAsync describe('this test', () => { test('looks async but is synchronous', fakeAsync((): void => { let flag = false; setTimeout(() => { flag = true; }, 100); expect(flag).toBe(false); tick(50); expect(flag).toBe(false); tick(50); expect(flag).toBe(true); })); }); Angular Unit Testing Angular https://angular.io/api/core/testing/fakeAsync

Slide 35

Slide 35 text

Testing Utilities: HttpTestingController https://www.techiediaries.com/angular-testing-httptestingcontroller/ Angular Unit Testing Angular

Slide 36

Slide 36 text

Test Watcher npm test -- --watch npm test -- --watch-all Angular Unit Testing Jest

Slide 37

Slide 37 text

Code Coverage npm test -- --coverage Code coverage provided by Istanbul Coverage metadata written to coverage folder Code coverage policy: ~ 80% Angular Unit Testing Angular P

Slide 38

Slide 38 text

Cypress https://www.cypress.io/ DevExpress TestCafé https://devexpress.github.io/testcafe/ Angular Unit Testing E2E Tests

Slide 39

Slide 39 text

Thank you for your kind attention! Christian Liebel @christianliebel [email protected]