我有一个类
A
,它从不同的模块导入类 B
并实例化它。在我对 A
类的测试中,我想存根/模拟 B
类的一些方法。
一些示例代码:
// 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');
})
我知道我可以使用构造函数注入而不是模拟模块,但我有一个情况是不可能的。
包 vitest-mock-extend 解决了这个问题:
// 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>()
}));
test('it stores formatted message', () => {
Formatter.format.mockReturnValue('formatted test message');
const store = new FormattedStore();
store.write('TestMessage');
expect(store.store[0]).toBe('formatted test message');
})