Auto Spy
ngMocks.autoSpy replaces empty methods on mocks created by ng-mocks with runner-native spies.
This is useful because the toHaveBeenCalled() matcher requires a spy or mock function;
without auto-spy, every asserted method must be wrapped explicitly.
Assume the suite setup already replaces UserService with an ng-mocks mock.
Without auto-spy, a Jasmine test needs explicit spyOn calls:
it('calls user.load', () => {
const userService = TestBed.inject(UserService);
spyOn(userService, 'init'); // why?
spyOn(userService, 'load'); // why?
spyOn(userService, 'set'); // why?
const fixture = TestBed.createComponent(UserComponent);
fixture.detectChanges();
expect(userService.init).toHaveBeenCalled();
expect(userService.load).toHaveBeenCalled();
expect(userService.set).toHaveBeenCalled();
});
By default, mock methods are empty functions which return undefined.
After enabling ngMocks.autoSpy, the test can omit the explicit spyOn calls:
it('calls user.load', () => {
const fixture = TestBed.createComponent(UserComponent);
fixture.detectChanges();
const userService = TestBed.inject(UserService);
expect(userService.init).toHaveBeenCalled();
expect(userService.load).toHaveBeenCalled();
expect(userService.set).toHaveBeenCalled();
});
Installation
Enable auto-spy once in the selected runner's setup file. It affects methods on mocked services, components, directives and pipes created by ng-mocks.
For Jasmine, add it to src/test.ts.
import { ngMocks } from 'ng-mocks';
ngMocks.autoSpy('jasmine');
// Uncomment if existing tests also install spies.
// jasmine.getEnv().allowRespy(true);
For Jest, add it to src/setup-jest.ts / src/test-setup.ts.
import { ngMocks } from 'ng-mocks';
ngMocks.autoSpy('jest');
For Vitest, add it to src/setup-vitest.ts.
import { ngMocks } from 'ng-mocks';
ngMocks.autoSpy('vitest');
See the native Vitest setup guide for how Angular loads this file.
Custom spy factory
To use another spy library, such as sinon.js, provide a custom factory:
ngMocks.autoSpy(spyName => {
return sinon.fake();
});
Temporarily change auto-spy
Pass default to make subsequently created mocks use empty functions instead of spies.
ngMocks.autoSpy('default');
Every non-reset call is stacked and each reset restores the previous choice:
beforeEach(() => ngMocks.autoSpy('jasmine'));
beforeEach(() => ngMocks.autoSpy('default'));
beforeEach(() => ngMocks.autoSpy('jasmine'));
afterEach(() => ngMocks.autoSpy('reset')); // now it is default
afterEach(() => ngMocks.autoSpy('reset')); // now it is jasmine
// out of calls, now it is default
afterEach(() => ngMocks.autoSpy('reset'));