lightsoutAlpha

jest-spyon-vs-jest-mock

`jest.mock` where a spy on the object already held would do, or the reverse

Agent checkadvisory by defaultbasetests

The argument

jest.spyOn vs jest.mock

  • Prefer jest.spyOn for a single method on an object you already hold (an injected service/repository), leaving the rest intact.
  • Prefer jest.mock for a standalone exported function from another module.

The proof

failsrc/orders/placeOrder.unit.test.ts
import { expect, describe, test, jest } from '@jest/globals';
import { placeOrder } from './placeOrder';

// The repository is an object the test already holds — replacing its whole
// module hides every other method the unit may touch.
const mockSave = jest.fn<(order: { id: string }) => void>();

jest.mock('./orderRepository', () => ({
	orderRepository: { save: (order: { id: string }) => mockSave(order) },
}));

describe('placeOrder', () => {
	test('saves the order it was given', () => {
		placeOrder({ order: { id: 'a' } });

		expect(mockSave).toHaveBeenCalledWith({ id: 'a' });
	});
});
passsrc/orders/placeOrder.unit.test.ts
import { expect, describe, test, jest } from '@jest/globals';
import { placeOrder } from './placeOrder';

const setupOrder = () => {
	const repository = { save: () => undefined };
	const saveSpy = jest.spyOn(repository, 'save');

	return { repository, saveSpy };
};

describe('placeOrder', () => {
	test('saves the order it was given', () => {
		const { repository, saveSpy } = setupOrder();

		placeOrder({ repository, order: { id: 'a' } });

		expect(saveSpy).toHaveBeenCalledWith({ id: 'a' });
	});
});

Turn it down

Both lines go in your lightsout.config.json.

"standards-checks": { "jest-spyon-vs-jest-mock": "advisory" }
"standards-checks": { "jest-spyon-vs-jest-mock": "off" }