如何使用 vitest 模拟 TypeScript 类

chi*_*org 8 mocking typescript vitest

我有一个类从不同的模块A导入类并实例化它。B在我对 class 的测试中,A我想存根/模拟 class 的一些方法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');
})

Run Code Online (Sandbox Code Playgroud)

我知道我可以使用构造函数注入而不是模拟模块,但我有一个不可能的情况。

Mor*_*oth 0

vitest-mock-extended包解决了这个问题:

// 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');
})
Run Code Online (Sandbox Code Playgroud)