javascript - 由于错误无法读取未定义的模拟实现,无法使用 Jest 测试发布方法
问题描述
我有一个 api 服务,我有不同的方法来调用 API。我已成功测试了所有 GET 请求,但在测试 POST 请求时遇到了麻烦。
这是方法:
export default class ApiService {
static makeApiCall = <T>(
url: string,
oneCb: <T>(d: Data) => T,
secondCb: (d: T) => void,
errorCb?: (a: ErrorModel) => void,
method = 'get',
data = {},
): Promise<void> => {
const config: AxiosRequestConfig = {};
if (method === 'post') {
config.headers = header;
return ApiClient.post(url, data, config)
.then(res => callback(normalizeCallback(res.data))).catch(error => someHandler(error));
} else {
return ApiClient.get(url)
.then(res => callback(normalizeCallback(res.data))).catch(error => someHandler(error));
}
};
// ONLY ONE POST METHOD TO MAKE IT MORE CLEAR
static someArchiveMethod = (
callback: (a: SuccessModel) => void,
errorCallback: (error: ErrorModel) => void,
cardId: string
): Promise<void> => {
return ApiService.makeApiCall<SuccessfulResponse>(
'appreciationCard/archive',
Normalizer.successfulResponse,
callback,
errorCallback,
'post',
{ cardId }
);
};
// HERE BELOW THE GET METHODS
static getPeople = (cb: (a: PeopleModel[]) => void, page?: number, limit?: number): Promise<void> => {
const queryDetails = { page, limit };
return ApiService.makeApiCall<PeopleModel[]>(
`people?${toQueryString(queryDetails)}`,
Normalizer.normalizePeople,
callback
);
};
};
这就是我测试与 GET 相关的所有内容的方式:
describe('apiService', () => {
beforeAll(() => {
expect(ApiClient.defaults.headers.common.Authorization).toBe('Bearer test token');
// @ts-ignore
ApiClient.get.mockImplementation((url: string) => {
return Promise.resolve({ data: mockData });
});
});
it('should call api client method', () => {
ApiService.makeApiCall(
'testUrl',
data => data,
res => res,
err => err,
'get'
);
expect(ApiClient.get).toBeCalledTimes(1);
expect(ApiClient.get).toBeCalledWith('testUrl');
});
it('should call callbacks consequently', done => {
ApiService.makeApiCall('testUrl', firstCallback, secondCallback).then(() => {
expect(firstCallback).toBeCalledTimes(1);
expect(firstCallback).toBeCalledWith(mockData);
expect(secondCallback).toBeCalledTimes(1);
expect(secondCallback).toBeCalledWith(firstCallback(mockData));
done();
});
});
});
describe('api service error flow', () => {
beforeAll(() => {
// @ts-ignore
ApiClient.get.mockImplementation((url: string) => {
console.log('error result');
return Promise.reject(mockError);
});
});
it('should handle error', done => {
console.error = jest.fn();
const firstCallback = jest.fn((data: any) => data);
const secondCallback = jest.fn((data: any) => data);
ApiService.makeApiCall('testUrl', firstCallback, secondCallback).then(() => {
expect(firstCallback).toBeCalledTimes(0);
expect(secondCallback).toBeCalledTimes(0);
expect(console.error).toBeCalledTimes(1);
expect(console.error).toBeCalledWith('ApiClient testUrl', mockError);
done();
});
});
});
describe('apiService methods', () => {
beforeAll(() => {
ApiClient.get.mockImplementation((url: string) => {
expect(ApiClient.defaults.headers.common.Authorization).toBe('Bearer test token');
return Promise.resolve({ data: mockData });
});
});
it('getPeople method call with one param', () => {
ApiService.getPeople(jest.fn(), 1, 1).then(() => {
expect(ApiClient.get).toBeCalledWith('people?page=1&limit=1');
});
});
})
我认为只有更改它的所有实例ApiClient.get
才能ApiClient.post
测试 POST 请求。但是当我尝试这样做时,它会这么说can not read mockImplementation of undefined
。我尝试更改测试中的方法以使用post
参数以覆盖参数method = 'get'
但我没有成功,我收到此错误
TypeError:apiClient_1.default.post 不是函数
有什么想法吗?
解决方案
我调查了你的问题。首先,我想告诉您,您的代码有几个问题,例如调用您未定义的回调、定义不明确ApiClient
等。
因此,我创建了一个 Repl 示例来重现您的问题,在该示例中我稍微简化了您的代码,但所有主要元素都在那里。
请看一下 https://repl.it/@SergeyMell/Some-Jesting
它适用于两种方法get
都post
没有问题。以下是您应该注意的要点:
- 用作.
axios
_ApiClient
(从你的问题中不清楚,所以我认为是这样)const ApiClient = require('axios');
- 设置玩笑
axios
(假设你也这样做)jest.mock('axios');
以类似的方式对两者
get
和请求进行模拟(与您的方式相同)post
ApiClient.get.mockImplementation((url) => { return Promise.resolve({ data: mockData }); }); ApiClient.post.mockImplementation((url) => { return Promise.resolve({ data: mockData }); });
因此,请检查我的示例,检查与您的代码的差异,并让我知道您可能需要一些额外的详细信息。
推荐阅读
- javascript - 在同一个 repo webpack 中的项目之间共享逻辑
- angularjs - 在 mat-select multiple 中更改复选框的大小
- javascript - 当Javascript中出现新消息时如何滚动到底部?
- count - 每个月 ID 过去 3 个月的滚动计数
- java - 从可执行文件中使用 Apache POI 输出会导致问号(编码错误?)
- javascript - 在 Windows 的所有桌面上显示应用程序窗口,但以编程方式
- python - Python tkinter 输入框和函数访问类外
- scala - 如何从 SocketTCP 获取数据以保存到 Spark Scala 中的数据帧?
- r - 自定义 DT 表的 html 输出中的文本
- swift - SwiftUI - 具有大量图像 URL 下载和显示的大型 JSON blob - 最佳实践?