mocking - Hur man mockar en TypeScript-klass med Vitest
Jag har en klass A som importerar klass B från en annan modul och skapar en instans av den. I mitt test för klass A skulle jag vilja stubba/mocka några av metoderna i klass B.
Exempel på kod:
// Formatter.ts
export class Formatter {
format(msg: string): string {
return `--- [INFO] ${msg}\n`;
}
}
// FormattedStore.ts
import {Formatter} from '@/Formatter'
export class FormattedStore implements Store {
public store: string[];
construct() {
this.formatter = new Formatter();
this.store = [];
}
write(msg: string): void {
this.store.push(this.formatter.format(msg));
}
}
// FormattedStore.spec.ts
import {FormattedStore} from '@/FormattedStore';
import {Formatter} from '@/Formatter'
import {vi, expect, test} from 'vitest';
vi.mock( '@/Formatter', () => ({
Formatter: vi.fn() // What's the correct and type-safe way to mock this?
}));
test('it stores formatted message', () => {
// How do I mock the formatter here with the return 'formatted test message'?
const store = new FormattedStore();
store.write('TestMessage');
expect(store.store[0]).toBe('formatted test message');
})
Jag vet att jag kunde använda konstruktörinjektion istället för att mocka modulen, men jag har ett fall där det inte är möjligt.
Svar #1
Paketet vitest-mock-extended löser detta:
// FormattedStore.spec.ts
import {mock} from 'vitest-mock-extended';
import {FormattedStore} from '@/FormattedStore';
import {Formatter} from '@/Formatter'
import {vi, expect, test} from 'vitest';
vi.mock( '@/Formatter', () => ({
Formatter: mock<Formatter>() // Mock class here
}));
test('it stores formatted message', () => {
Formatter.format.mockReturnValue('formatted test message'); // provide return values here
const store = new FormattedStore();
store.write('TestMessage');
expect(store.store[0]).toBe('formatted test message');
})
