Kam*_*ran 6 mocking reactjs axios react-testing-library
我想用react-testing-library测试我的api 并且我从一个名为 apiClient.ts 的文件中导出由 axios.create 创建的实例
import axios from 'axios'
const apiClient = axios.create({
baseURL: process.env.REACT_APP_API_URL,
responseType: 'json',
headers: {
'Content-Type': 'application/json',
},
})
export default apiClientRun Code Online (Sandbox Code Playgroud)
然后在 users.ts fetchUsersApi 中使用我从 apiClient 获取的 axios 实例
import apiClient from './apiClient'
export interface ITrader {
id: number
name: string
username: string
email: string
address: any
phone: string
website: string
company: any
}
export const fetchTradersApi = async (): Promise<ITrader[]> => {
const response = await apiClient.get<ITrader[]>('/users')
return response.data
}Run Code Online (Sandbox Code Playgroud)
我创建了一个mocks文件夹并在其中添加了axios.ts
export default {
get: jest.fn(() => Promise.resolve({ data: {} })),
}Run Code Online (Sandbox Code Playgroud)
我的 users.spec.tsx 看起来像:
import { cleanup } from '@testing-library/react'
import axiosMock from 'axios'
import { fetchTradersApi } from './traders'
jest.mock('axios')
describe.only('fetchTradersApi', () => {
afterEach(cleanup)
it('Calls axios and returns traders', async () => {
axiosMock.get.mockImplementationOnce(() =>
Promise.resolve({
data: ['Jo Smith'],
})
)
const traders = await fetchTradersApi()
expect(traders).toBe([{ name: 'Jo Smith' }])
expect(axiosMock.get).toHaveBeenCalledTimes(1)
expect(axiosMock.get).toHaveBeenCalledWith(`${process.env.REACT_APP_API_URL}/users`)
})
})Run Code Online (Sandbox Code Playgroud)
我运行测试并得到: 测试套件运行失败
TypeError: _axios.default.create is not a function
1 | import axios from 'axios'
2 |
> 3 | const apiClient = axios.create({
Run Code Online (Sandbox Code Playgroud)
请提前创建一个与 React-testing-library、Tnx 配合使用的适当的 axios 模拟,帮助我解决问题。
经过一整天的努力,我找到了与我遇到的完全相同的问题的解决方案。我遇到的问题与 JEST、Node 和 Typescript 组合有关。让我简单介绍一下在此发挥作用的文件:
axios-instance.ts
import axios, { AxiosInstance } from "axios";
const axiosInstance: AxiosInstance = axios.create({
baseURL: `https://example-path/products/`,
headers: {
'Content-Type': 'application/json'
}
});
export default axiosInstance;
Run Code Online (Sandbox Code Playgroud)
api.ts
"use strict";
import {Request, Response, RequestHandler, NextFunction} from "express";
import axiosInstance from "./axios-instance";
/**
* POST /:productId
* Save product by productId
*/
export const save: RequestHandler = async (req: Request, res: Response, next: NextFunction) => {
try {
const response = await axiosInstance.post(`${req.params.id}/save`, req.body);
res.status(response.status).json(response.data);
} catch (error) {
res.status(error.response.status).json(error.response.data);
}
};
Run Code Online (Sandbox Code Playgroud)
api 规范.ts
import { save } from "./api";
import axiosInstance from "./axios-instance";
describe.only("controller", () => {
describe("test save", () => {
let mockPost: jest.SpyInstance;
beforeEach(() => {
mockPost = jest.spyOn(axiosInstance, 'post');
});
afterEach(() => {
jest.clearAllMocks();
});
it("should save data if resolved [200]", async () => {
const req: any = {
params: {
id: 5006
},
body: {
"productName": "ABC",
"productType": "Food",
"productPrice": "1000"
}
};
const res: any = {
status: () => {
return {
json: jest.fn()
}
},
};
const result = {
status: 200,
data: {
"message": "Product saved"
}
};
mockPost.mockImplementation(() => Promise.resolve(result));
await save(req, res, jest.fn);
expect(mockPost).toHaveBeenCalled();
expect(mockPost.mock.calls.length).toEqual(1);
const mockResult = await mockPost.mock.results[0].value;
expect(mockResult).toStrictEqual(result);
});
it("should not save data if rejected [500]", async () => {
const req: any = {
params: {
id: 5006
},
body: {}
};
const res: any = {
status: () => {
return {
json: jest.fn()
}
},
};
const result = {
response: {
status: 500,
data: {
"message": "Product is not supplied"
}
}
};
mockPost.mockImplementation(() => Promise.reject(result));
await save(req, res, jest.fn);
expect(mockPost).toHaveBeenCalled();
const calls = mockPost.mock.calls.length;
expect(calls).toEqual(1);
});
});
});
Run Code Online (Sandbox Code Playgroud)
对于发布的要求,我们必须模拟“axiosInstance”而不是库中实际的“axios”对象,因为我们正在从 axiosInstance 进行调用。
在规范文件中,我们导入了 axiosInstance 而不是实际的 axios
import axiosInstance from "./axios-instance";
Run Code Online (Sandbox Code Playgroud)
然后我们为 post 方法创建了一个间谍(获取/发布/放置任何你可以监视的内容)
let mockPost: jest.SpyInstance;
Run Code Online (Sandbox Code Playgroud)
在每个测试用例之前进行初始化,以便每个测试用例都有一个新的间谍开始,并且在每个测试用例之后还需要清除模拟。
beforeEach(() => {
mockPost = jest.spyOn(axiosInstance, 'post');
});
afterEach(() => {
jest.clearAllMocks();
});
Run Code Online (Sandbox Code Playgroud)
模拟实施已解决/拒绝
mockPost.mockImplementation(() => Promise.resolve(result));
mockPost.mockImplementation(() => Promise.reject(result));
Run Code Online (Sandbox Code Playgroud)
然后调用实际的方法
await save(req, res, jest.fn);
Run Code Online (Sandbox Code Playgroud)
检查预期结果
expect(mockPost).toHaveBeenCalled();
expect(mockPost.mock.calls.length).toEqual(1);
const mockResult = await mockPost.mock.results[0].value;
expect(mockResult).toStrictEqual(result);
Run Code Online (Sandbox Code Playgroud)
希望它对您有所帮助,并且您可以将解决方案与您的问题联系起来。谢谢
| 归档时间: |
|
| 查看次数: |
6820 次 |
| 最近记录: |