Unit Testing Cookbook
[🚧 This file is under construction]
Test Structure​
describe('$className$', () => {
beforeAll(() => {
$customElements$
});
beforeEach(async () => {
$subjectImplementations$
await TestBed.configureTestingModule({
imports: [
$components$,
$pipes$,
$directives$
],
providers: [
$providedInRootServices$,
$routerServices$
],
declarations: [
$mockedComponents$
]
});
});
});
HTML/DOM Testing​
- Use DebugElement instead of native query selectors.
- Benefits:
- Platform independent abstraction
- Event simulation
- Cross-platform support
Method Call Testing​
it('should spy on method', () => {
const user = { activate: jest.fn() };
const spy = jest.spyOn(user, 'activate');
user.activate();
expect(spy).toHaveBeenCalled();
});
Data Provider Testing with it.each​
function sum(a: number, b: number): number {
return a + b;
}
describe('sum function with it.each', () => {
it.each([
[0, 1, 1],
[5, 3, 8],
[-2, 4, 2],
[10, -5, 5],
[0, 100, 100],
])(
'should return the correct sum for %s + %s = %s',
(a, b, expected) => {
expect(sum(a, b)).toBe(expected);
}
);
});
Updating Component Inputs​
describe('OverviewCardComponent', () => {
let component: OverviewCardComponent;
let fixture: ComponentFixture<OverviewCardComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [MyComponent],
}).compileComponents();
fixture = TestBed.createComponent(MyComponent);
component = fixture.componentInstance;
});
it('should update input', () => {
fixture.componentRef.setInput('myInput', false);
fixture.detectChanges();
});
});
Globals Testing​
Console Error Mocking​
it('should handle exceptions in the log.', async () => {
const errorLogSpy = jest
.spyOn(global.console, 'error')
.mockImplementation(jest.fn());
console.error('my error')
expect(errorLogSpy).toHaveBeenCalled();
});
...
TODO​
- Add templates for fast implementation
- Improve ESLint compatibility for
max-classes-per-file
Note: All interactions are done using data-test properties, not CSS class selectors.