如何模拟 AxiosInstance?
How to mock AxiosInstance?
我有 axios
和以下 HttpClient
class
export default class HttpClient {
constructor(baseUrl: string) {
const axiosInstance = axios.create({
validateStatus(status: number) {
return status === 200 || status === 201;
},
});
axiosInstance.interceptors.request.use((config) => {
if (AuthUtil.getAuthHeader()) config.headers = AuthUtil.getAuthHeader();
return config;
});
return new Proxy(this, {
get(_, prop) {
return (url: string, ...args: any) => {
url = baseUrl + url;
return Reflect.get(axiosInstance, prop)(url, ...args);
};
},
});
}
get<T = any, R = AxiosResponse<T>>(_url: string, _config?: AxiosRequestConfig): Promise<R> {
return Promise.resolve(null);
}
.....
}
这是使用 HttpClient
的服务
export default class UserManagementServiceImpl implements UserManagementService {
private client = new HttpClient('/api/user');
async getUser(): Promise<User> {
const res = await this.client.get('/user');
return res.data;
}
我正在按如下方式测试服务。在这里我没有直接调用 userService.getUser
而是为了测试我创建了这个。
describe('User actions', () => {
test('creates GET_TERMS_SUCCESS', async () => {
jest.mock('axios', () => {
return {
create: jest.fn().mockReturnValue({
interceptors: {
request: { use: jest.fn(), eject: jest.fn() },
response: { use: jest.fn(), eject: jest.fn() },
},
get: jest.fn().mockReturnValue({ data: user }),
}),
};
});
const user = await userService.getUser();
});
});
// ERROR:
/*
Error: Error: connect ECONNREFUSED 127.0.0.1:80
*/
我已经尝试了堆栈溢出中列出的其他多种解决方案,但似乎没有用。应该怎么做?
更新 [2022 年 5 月 18 日]
我想我终于想出了如何结合 axios-mock-adapter
来模拟 axios.create()
创建的 AxiosInstance
es。
我们在测试中所做的是,将 AxiosStatic
实例分配为 axios.create
的 return 值,该实例可在本地访问。所以我们像往常一样模拟 axios
using axios-mock-adapter
.
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import UserManagementServiceImpl from '../../../services/impl/UserManagementServiceImpl';
jest.mock('axios', () => {
return {
...(jest.requireActual('axios') as object),
create: jest.fn().mockReturnValue(jest.requireActual('axios')),
};
});
const mockAdapter = new MockAdapter(axios);
test('hello', async () => {
const userService = new UserManagementServiceImpl();
mockAdapter.onGet('/api/user/user').reply(200, { name: 'name' });
const r = (await userService.getUser()) as any;
expect(r.name).toBe('name');
});
旧答案
jest.mock() 显然应该始终在测试生命周期方法之外。
jest.mock('axios', () => {
return {
create: jest.fn().mockReturnValue({
interceptors: {
request: { use: jest.fn(), eject: jest.fn() },
response: { use: jest.fn(), eject: jest.fn() },
},
get: jest.fn().mockReturnValue({ data: user }),
}),
};
});
describe('User actions', () => {
test('test', async () => {
const user = await userService.getUser();
});
});
您也可以稍后模拟和定义函数
jest.mock('axios')
describe('User actions', () => {
test('test', async () => {
(axios.create as jest.Mock<any, any>).mockReturnValue({
interceptors: {
request: { use: jest.fn(), eject: jest.fn() },
response: { use: jest.fn(), eject: jest.fn() },
},
get: jest.fn().mockReturnValue({ data: { name: 'name' } }),
});
const user = await userService.getUser();
});
});
我有 axios
和以下 HttpClient
class
export default class HttpClient {
constructor(baseUrl: string) {
const axiosInstance = axios.create({
validateStatus(status: number) {
return status === 200 || status === 201;
},
});
axiosInstance.interceptors.request.use((config) => {
if (AuthUtil.getAuthHeader()) config.headers = AuthUtil.getAuthHeader();
return config;
});
return new Proxy(this, {
get(_, prop) {
return (url: string, ...args: any) => {
url = baseUrl + url;
return Reflect.get(axiosInstance, prop)(url, ...args);
};
},
});
}
get<T = any, R = AxiosResponse<T>>(_url: string, _config?: AxiosRequestConfig): Promise<R> {
return Promise.resolve(null);
}
.....
}
这是使用 HttpClient
export default class UserManagementServiceImpl implements UserManagementService {
private client = new HttpClient('/api/user');
async getUser(): Promise<User> {
const res = await this.client.get('/user');
return res.data;
}
我正在按如下方式测试服务。在这里我没有直接调用 userService.getUser
而是为了测试我创建了这个。
describe('User actions', () => {
test('creates GET_TERMS_SUCCESS', async () => {
jest.mock('axios', () => {
return {
create: jest.fn().mockReturnValue({
interceptors: {
request: { use: jest.fn(), eject: jest.fn() },
response: { use: jest.fn(), eject: jest.fn() },
},
get: jest.fn().mockReturnValue({ data: user }),
}),
};
});
const user = await userService.getUser();
});
});
// ERROR:
/*
Error: Error: connect ECONNREFUSED 127.0.0.1:80
*/
我已经尝试了堆栈溢出中列出的其他多种解决方案,但似乎没有用。应该怎么做?
更新 [2022 年 5 月 18 日]
我想我终于想出了如何结合 axios-mock-adapter
来模拟 axios.create()
创建的 AxiosInstance
es。
我们在测试中所做的是,将 AxiosStatic
实例分配为 axios.create
的 return 值,该实例可在本地访问。所以我们像往常一样模拟 axios
using axios-mock-adapter
.
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import UserManagementServiceImpl from '../../../services/impl/UserManagementServiceImpl';
jest.mock('axios', () => {
return {
...(jest.requireActual('axios') as object),
create: jest.fn().mockReturnValue(jest.requireActual('axios')),
};
});
const mockAdapter = new MockAdapter(axios);
test('hello', async () => {
const userService = new UserManagementServiceImpl();
mockAdapter.onGet('/api/user/user').reply(200, { name: 'name' });
const r = (await userService.getUser()) as any;
expect(r.name).toBe('name');
});
旧答案
jest.mock() 显然应该始终在测试生命周期方法之外。
jest.mock('axios', () => {
return {
create: jest.fn().mockReturnValue({
interceptors: {
request: { use: jest.fn(), eject: jest.fn() },
response: { use: jest.fn(), eject: jest.fn() },
},
get: jest.fn().mockReturnValue({ data: user }),
}),
};
});
describe('User actions', () => {
test('test', async () => {
const user = await userService.getUser();
});
});
您也可以稍后模拟和定义函数
jest.mock('axios')
describe('User actions', () => {
test('test', async () => {
(axios.create as jest.Mock<any, any>).mockReturnValue({
interceptors: {
request: { use: jest.fn(), eject: jest.fn() },
response: { use: jest.fn(), eject: jest.fn() },
},
get: jest.fn().mockReturnValue({ data: { name: 'name' } }),
});
const user = await userService.getUser();
});
});