dun*_*all 15 mocking node.js typescript reactjs jestjs
当想要使用Jest模拟外部模块时,我们可以使用该jest.mock()方法自动模拟模块上的函数.
然后,我们可以按照我们的意愿操纵和查询模拟模块上的模拟函数.
例如,考虑以下用于模拟axios模块的设计示例:
import myModuleThatCallsAxios from '../myModule';
import axios from 'axios';
jest.mock('axios');
it('Calls the GET method as expected', async () => {
const expectedResult: string = 'result';
axios.get.mockReturnValueOnce({ data: expectedResult });
const result = await myModuleThatCallsAxios.makeGetRequest();
expect(axios.get).toHaveBeenCalled();
expect(result).toBe(expectedResult);
});
Run Code Online (Sandbox Code Playgroud)
以上将在Jest中正常运行,但会抛出一个Typescript错误:
属性'mockReturnValueOnce'在类型'(url:string,config?:AxiosRequestConfig | undefined)=> AxiosPromise'上不存在.
typedef axios.get正确不包含mockReturnValueOnce属性.我们可以强制将Typescript axios.get包装为Object文字Object(axios.get),但是:
在保持类型安全的同时模拟功能的惯用方法是什么?
小智 32
添加这行代码const mockedAxios = axios as jest.Mocked<typeof axios>.然后使用mockedAxios来调用mockReturnValueOnce.使用您的代码,应该这样做:
import myModuleThatCallsAxios from '../myModule';
import axios from 'axios';
jest.mock('axios');
const mockedAxios = axios as jest.Mocked<typeof axios>;
it('Calls the GET method as expected', async () => {
const expectedResult: string = 'result';
mockedAxios.get.mockReturnValueOnce({ data: expectedResult });
const result = await myModuleThatCallsAxios.makeGetRequest();
expect(mockedAxios.get).toHaveBeenCalled();
expect(result).toBe(expectedResult);
});
Run Code Online (Sandbox Code Playgroud)
Mel*_*hia 14
mocked从ts-jest 27.0 开始,ts-jest将在 28.0 中弃用并删除,您可以在官方文档中查看。所以请使用jest.mockedfrom代替jest。这是文档
所以对于你的例子:
import myModuleThatCallsAxios from '../myModule';
import axios from 'axios';
jest.mock('axios');
// OPTION - 1
const mockedAxios = jest.mocked(axios, true)
// your original `it` block
it('Calls the GET method as expected', async () => {
const expectedResult: string = 'result';
mockedAxios.mockReturnValueOnce({ data: expectedResult });
const result = await myModuleThatCallsAxios.makeGetRequest();
expect(mockedAxios.get).toHaveBeenCalled();
expect(result).toBe(expectedResult);
});
Run Code Online (Sandbox Code Playgroud)
Bri*_*ams 12
要在保持类型安全的同时习惯性地模拟该函数,请使用spyOn结合mockReturnValueOnce:
import myModuleThatCallsAxios from '../myModule';
import axios from 'axios';
it('Calls the GET method as expected', async () => {
const expectedResult: string = 'result';
// set up mock for axios.get
const mock = jest.spyOn(axios, 'get');
mock.mockReturnValueOnce({ data: expectedResult });
const result = await myModuleThatCallsAxios.makeGetRequest();
expect(mock).toHaveBeenCalled();
expect(result).toBe(expectedResult);
// restore axios.get
mock.mockRestore();
});
Run Code Online (Sandbox Code Playgroud)
提供导入新功能以扩展原始模块(如)的常用方法declare module "axios" { ... }。这不是最佳选择,因为这应该在整个模块中完成,而模拟可能在一个测试中可用而在另一个测试中不可用。
在这种情况下,类型安全的方法是在需要时声明类型:
(axios.get as jest.Mock).mockReturnValueOnce({ data: expectedResult });
...
expect(axios.get as jest.Mock).toHaveBeenCalled();
Run Code Online (Sandbox Code Playgroud)
axios.get@hutabalian 当您使用or时,代码效果非常好axios.post,但如果您使用configfor 请求,则以下代码:
const expectedResult: string = 'result';
const mockedAxios = axios as jest.Mocked<typeof axios>;
mockedAxios.mockReturnValueOnce({ data: expectedResult });
Run Code Online (Sandbox Code Playgroud)
会导致这个错误:
TS2339 (TS) 类型“Mocked”上不存在属性“mockReturnValueOnce”。
你可以这样解决:
AxiosRequest.test.tsx
import axios from 'axios';
import { MediaByIdentifier } from '../api/mediaController';
jest.mock('axios', () => jest.fn());
test('Test AxiosRequest',async () => {
const mRes = { status: 200, data: 'fake data' };
(axios as unknown as jest.Mock).mockResolvedValueOnce(mRes);
const mock = await MediaByIdentifier('Test');
expect(mock).toEqual(mRes);
expect(axios).toHaveBeenCalledTimes(1);
});
Run Code Online (Sandbox Code Playgroud)
媒体控制器.ts:
import { sendRequest } from './request'
import { AxiosPromise } from 'axios'
import { MediaDto } from './../model/typegen/mediaDto';
const path = '/api/media/'
export const MediaByIdentifier = (identifier: string): AxiosPromise<MediaDto> => {
return sendRequest(path + 'MediaByIdentifier?identifier=' + identifier, 'get');
}
Run Code Online (Sandbox Code Playgroud)
请求.ts:
import axios, { AxiosPromise, AxiosRequestConfig, Method } from 'axios';
const getConfig = (url: string, method: Method, params?: any, data?: any) => {
const config: AxiosRequestConfig = {
url: url,
method: method,
responseType: 'json',
params: params,
data: data,
headers: { 'X-Requested-With': 'XMLHttpRequest', 'Content-Type': 'application/json' },
}
return config;
}
export const sendRequest = (url: string, method: Method, params?: any, data?: any): AxiosPromise<any> => {
return axios(getConfig(url, method, params, data))
}
Run Code Online (Sandbox Code Playgroud)
小智 5
请使用以下mocked功能ts-jest
import myModuleThatCallsAxios from '../myModule';
import axios from 'axios';
jest.mock('axios');
// OPTION - 1
const mockedAxios = mocked(axios, true)
// your original `it` block
it('Calls the GET method as expected', async () => {
const expectedResult: string = 'result';
mockedAxios.mockReturnValueOnce({ data: expectedResult });
const result = await myModuleThatCallsAxios.makeGetRequest();
expect(mockedAxios.get).toHaveBeenCalled();
expect(result).toBe(expectedResult);
});
// OPTION - 2
// wrap axios in mocked at the place you use
it('Calls the GET method as expected', async () => {
const expectedResult: string = 'result';
mocked(axios).get.mockReturnValueOnce({ data: expectedResult });
const result = await myModuleThatCallsAxios.makeGetRequest();
// notice how axios is wrapped in `mocked` call
expect(mocked(axios).get).toHaveBeenCalled();
expect(result).toBe(expectedResult);
});
Run Code Online (Sandbox Code Playgroud)
我无法强调有多伟大mocked,再也没有类型转换。
| 归档时间: |
|
| 查看次数: |
9939 次 |
| 最近记录: |