Jasmine cheatsheet

What is Jasmine

Testing framework for Javascript, independent from browser or DOM

  • Behavior driven tests: describe what it does
  • Tests or “specs” are independent in every describe, they are launched with it
  • Group the tests by functionality: you may nest the describe
  • A var declared inside the describe is available for all the it contexts it has
  • Each test has one or more expect, which similar to the Junit assert -> true or false depending on the code status
  • Beware! if a test function mutates dummy data, all tests after that using the same data will receive the mutated version
  • For Angular components, if $onInit() or $onChanges() exists, it should be called at the end of the beforeEach block, after the component instantiation
  • Component bindings should be public, since they are part of the component’s public interface

Tips

  • Create dummy values to reuse them (Test-beds).
  • Simple “it” blocks, should not depend on other blocks
  • Call the function you want to test
  • Test a single thing: reduce to a single Assert /Expect/Verify line
  • Always have a “it should create” test function before all other test functions

Tests

1
2
3
4
5
6
7
8
9
10
describe('Sorting a list of users', () => {
it('sorts in descending order by default', () => {
// prepare step
let users = ['Hofer10', 'Bower05', 'Smith20'];
// execution step
let sorted = sortUSers(users);
// expectations step
expect(true).toEqual(['Bower05', 'Hofer10', 'smith20']);
})
})

Hooks

1
2
3
4
5
6
7
beforeEach(() => {
// shared test setup
})

afterEach(() => {
// clean up after tests, report
})

Matchers

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
expect(array).toContain(member);
expect(fn).toThrow(string);
expect(fn).toThrowError(string);
expect(instance).toBe(instance));
expect(mixed).toBeDefined();
expect(mixed)toBeFalsy();
expect(mixed).toBeNull(),
expect(mixed).toBeTruthy();
expect(mixed).toBeUndefined();
expect(mixed).toEqual(mixed);
expect(mixed)toMatch(pattern);
expect(number).toBeCloseTo(number, decimalPlaces);
expect(number).toBeGreaterThan(number);
expect(number).toBeLesserThan(number);
expect(number).toBeNaN();
expect(spy).toHaveBeenCalled();
expect(spy).toHaveBeenCalledTimes(number);
expect(spy).toHaveBeenCalledWith(...arguments);

Mocks

1
2
3
4
5
6
7
8
ley myModal: MyModal;
// mocked service, which can be spied
let myServiceSpy: jasmine.spyObj<MyService>;

beforeEach(() => {
myServiceSpy = jasmine.createSpyObj('myService', [' myVariable']);
myModal = new MyModal(myServiceSpy);
});

Spy

1
2
3
4
5
6
7
8
9
spyOn(foo, 'setBar')
spyOn(foo, 'setBar').andReturn(123)
spyOn(foo, 'getBar').andCallFake(function() { return 1001; })
foo.setBar(123)

expect(foo.setBar).toHaveBeenCalled()
expect(foo.setBar).toHaveBeenCalledWith(123)
expect(foo.setBar.calls.length).toEqual(2)
expect(foo.setBar.calls[0].args[0]).toEqual(123)

Async

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
describe('works with promises', () => {
return new Promise((resolve, reject) => {
···
})
})

describe('Ammend role modal', () => {
// Functions with have async logic but do not return the promise
// can only be tested for their spies functions to be called
it ('validateAmmendedRoles should have been called', () =>{
rolesServiceSpy.validateRoles.and.return.value(Promise.resolve([]));
await modal.validateAmmendedRoles();
expect(uibModalInstanceSpy.close()).toHaveBeenCalled();
});
});