由于错误无法读取未定义的模拟实现,无法使用 Jest 测试发布方法
Posted
技术标签:
【中文标题】由于错误无法读取未定义的模拟实现,无法使用 Jest 测试发布方法【英文标题】:Unable to test post methods with Jest due to error can not read mockImplementation of undefined 【发布时间】:2020-05-11 07:20:52 【问题描述】:我有一个 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
没有方法post
。
嗨,@Tomas 看看这一行 -> return ApiClient.post(url, data, config) .then(res => callback(normalizeCallback(res.data))).catch(error => someHandler(error));
当我尝试发出帖子请求时它可以正常工作。我的意思是我有 17 个帖子请求可以正常工作。那么为什么在测试中不起作用呢?
@Reacting 请分享“post”单元测试示例
@OronBen-David 我在问题中提到我尝试与get
测试中的完全相同,但我更改了get
的所有实例并改为设置post
。跨度>
我明白了,但是提一下不工作的代码会更清楚
【参考方案1】:
我已经调查了您的问题。首先,我想告诉你,你的代码有几个问题,比如调用你没有定义的回调,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 );
);
所以,请检查我的示例,检查与您的代码的差异,并让我知道您可能需要一些额外的详细信息。
【讨论】:
【参考方案2】:请尝试将mockImplementation
更改为mockImplementationOnce
【讨论】:
以上是关于由于错误无法读取未定义的模拟实现,无法使用 Jest 测试发布方法的主要内容,如果未能解决你的问题,请参考以下文章
ReactJS TypeError:无法读取未定义的属性(读取“地图”)