This document provides an overview of unit testing in Angular, including setting up Angular CLI for testing, the tools used for testing like Karma and Jasmine, how to write test specs with expectations and matchers, how to set up and tear down tests, and how to test different parts of an Angular application like components, templates, dependencies, and HTTP services. The agenda also includes debugging tests and generating code coverage reports.
Angular Unit Testing
ShailendraChauhan
Founder & CEO - Dot Net Tricks
#ngIndia www.ng-ind.com Feb 24, 2018
Microsoft MVP
ng-India
2.
• What isUnit Testing?
• Angular CLI Setup
• Angular Testing Tools
• Jasmine Test Spec
• Setup and Teardown
• Testing A Simple Component
• Debugging and Code Coverage
• Testing A Component with Template and Dependencies
• Testing Http Service
Agenda
3.
• A unittesting is a method, where each unit or component of a
software is tested to determine whether it is fit for use or not
• A single unit is any block of code (i.e. function or class) that
has one and only one responsibility
• A function might have multiple unit tests according to the uses
and output of the function
What is Unit Testing?
Angular Testing Tools
TestRunner
Karma
Test Framework
Jasmine
Test Utilities
Angular (TestBed,
ComponentFixture)
6.
Jasmine Test Spec
describe(str,fn)
• A Test Suite
• Contains Test Specs
it(str, fn)
• A Test Spec
• Contains 1 or more
test expectations
expect(actual)
• An expected piece
of behavior
matcher(expected)
• Does a boolean
comparison
• toEqual, toContain,
toBeNull
7.
Setup and Teardown(cleaningup)
beforeAll()
• Called once, before
all the specs in a
test suite run
beforeEach()
• Called before each
test spec run
afterAll()
• Called once, after
all the specs in a
test suite finished
afterEach()
• Called after each
test spec run
#4 End-to-end tests explore the application as users experience it.
#5 Jasmine - It provides everything needed to write basic tests. It ships with an HTML test runner that executes tests in the browser.
Karma - It is ideal for writing and running unit tests while developing the application.
Protractor - It is used to write and run end-to-end (e2e) tests. In e2e testing, one process runs the real application and a second process runs protractor tests that simulate user behavior and assert that the application respond in the browser as expected. End-to-end tests explore the application as users experience it.
#6 Jasmine - It provides everything needed to write basic tests. It ships with an HTML test runner that executes tests in the browser.
Karma - It is ideal for writing and running unit tests while developing the application.
Protractor - It is used to write and run end-to-end (e2e) tests. In e2e testing, one process runs the real application and a second process runs protractor tests that simulate user behavior and assert that the application respond in the browser as expected. End-to-end tests explore the application as users experience it.
Karma – A test runner for running unit tests.
Jasmine – A framework for writing basic tests. It ships with an HTML test runner that executes tests in the browser.
Test Utilities – Angular provides classes like TestBed, Component Fixture, Mock backend and several helper functions for unit tests.
#7 The describe(string, function) defines a collection of Test Specs, called as Test Suite
The it(string, function) defines a Test Spec, containing one or more Test expectations
The expect(actual) describes an expected piece of behaviour in the application
The matcher(expected) like toEqual, toContain, toBeNull does a boolean comparison of the expected value with actual value
You can do negative assertion with not
describe('Hello world', () => {
it('says hello', () => {
expect(helloWorld())
.toEqual('Hello world!');
});
it('not equal to Hello', () => {
expect(helloWorld())
.not.toEqual('Hello!');
});
});
#8 The describe(string, function) defines a collection of Test Specs, called as Test Suite
The it(string, function) defines a Test Spec, containing one or more Test expectations
The expect(actual) describes an expected piece of behaviour in the application
The matcher(expected) like toEqual, toContain, toBeNull does a boolean comparison of the expected value with actual value
You can do negative assertion with not
describe('Hello world', () => {
it('says hello', () => {
expect(helloWorld())
.toEqual('Hello world!');
});
it('not equal to Hello', () => {
expect(helloWorld())
.not.toEqual('Hello!');
});
});
#9 Testbed configures and initializes environment for unit testing and provides methods for creating components and services in unit tests.
component fixture helps you to test and debug a component class and it’s dom
nativeElement is a reference to the DOM element
DebugElement is an Angular2 class that contains all kinds of references and methods, to investigate an element or component
Async() will allow the next test not to start until the async finishes all it's tasks. It tells to the test framework to wait until the return promise or observable is completed before treating the test as completed.
fixture.detectChanges() : trigger change detection
toBeTruthy() - Check if the value, when cast to a boolean, will be a truthy value i.e. Truthy values are all values that aren't 0, '' (empty string), false, null, NaN, undefinedor [] (empty array)*.
To test if something evaluates to true, you use the toBeTruthy matcher:
expect(true).toBeTruthy();
expect(12).toBeTruthy();
expect({}).toBeTruthy();
Likewise, to test if something evaluates to false, you use toBeFalsy:
expect(false).toBeFalsy();
expect(null).toBeFalsy();
expect("").toBeFalsy();
WebPack developers need not to call compileComponents since it inlines templates and css as part of the automated build process that precedes running the test.
Component = new componentclass() vs component-fixture-createinstance
Isolated tests are for when you only want to test the internal behavior of the class. For instance
class MyComponent { doSomething(): string {} } let component = new MyComponent(); expect(component.doSomething()).toBe('Hello World'); Here you're only going to test the behavior of the doSomething method. That's it.
With the isolated tests you can't test the DOM interaction, as the template is never compiled. For this we should let Angular create the component. Then the component will go through through the actual lifecycle it would go through as it it was in the real application
ng test --watch - To watch and re-run only the tests which have changed
ng test --coverage - Free code coverage report
#12 Spy is a jasmine feature, where we skip the original object/class method call and pass your own implementation.
Testbed configures and initializes environment for unit testing and provides methods for creating components and services in unit tests.
component fixture helps you to test and debug a component class and it’s dom
nativeElement is a reference to the DOM element
DebugElement is an Angular2 class that contains all kinds of references and methods, to investigate an element or component
Async() will allow the next test not to start until the async finishes all it's tasks. It tells to the test framework to wait until the return promise or observable is completed before treating the test as completed.
fixture.detectChanges() : trigger change detection
toBeTruthy() - Check if the value, when cast to a boolean, will be a truthy value i.e. Truthy values are all values that aren't 0, '' (empty string), false, null, NaN, undefinedor [] (empty array)*.
To test if something evaluates to true, you use the toBeTruthy matcher:
expect(true).toBeTruthy();
expect(12).toBeTruthy();
expect({}).toBeTruthy();
Likewise, to test if something evaluates to false, you use toBeFalsy:
expect(false).toBeFalsy();
expect(null).toBeFalsy();
expect("").toBeFalsy();
WebPack developers need not to call compileComponents since it inlines templates and css as part of the automated build process that precedes running the test.
Component = new componentclass() vs component-fixture-createinstance
Isolated tests are for when you only want to test the internal behavior of the class. For instance
class MyComponent { doSomething(): string {} } let component = new MyComponent(); expect(component.doSomething()).toBe('Hello World'); Here you're only going to test the behavior of the doSomething method. That's it.
With the isolated tests you can't test the DOM interaction, as the template is never compiled. For this we should let Angular create the component. Then the component will go through through the actual lifecycle it would go through as it it was in the real application
ng test --watch - To watch and re-run only the tests which have changed
ng test --coverage - Free code coverage report