我正在尝试编写一个测试,以确保在适当的情况下,使用特定的消息调用特定的函数(在这种情况下为哨兵函数)。但是,当我编写此测试时,它失败了,并且收到以下消息。如何正确模拟captureMessage
中的handleError.test.js
函数,以确保使用"this is an error message."
中的handleError.js
字符串正确地调用它?谢谢!
错误消息:
错误:期望(jest.fn())[。not] .toHaveBeenCalledWith()
jest.fn()值必须是模拟函数或间谍程序。收到:功能: [功能captureMessage]
handleError.js:
import {captureMessage} from '@sentry/browser';
const handleError = (error) => {
if (error.name === "ApiError") {
captureMessage('this is an error message.');
}
};
export default handleError;
handleError.test.js:
import {captureMessage} from '@sentry/browser';
import handleError from '../handleError';
class ApiError extends Error {
constructor() {
super();
this.name = 'ApiError';
}
}
test('When an ApiError is returned with no action type, sentry is notified', () => {
const sampleError = new ApiError();
handleError(sampleError);
expect(captureMessage).toHaveBeenCalledWith('this is an error message.');
});
答案 0 :(得分:2)
正如@balzee所述,您实际上必须监视要断言的方法。这导致Jest用特殊的间谍函数替换该方法,该函数跟踪被调用的参数,被调用的次数等等。
您还应该为该功能提供一个模拟实现,以免在运行单元测试时实际上不呼唤Sentry。
最后,当监视一个方法时,首先传递该方法所在的对象,然后将该方法的名称作为字符串传递。然后,Jest用一个间谍函数替换该对象上的该属性,如果没有给出模拟实现,它将调用原始函数。
如果不引用函数所在的对象,则只需将本地函数变量指向的对象从原始/实函数更改为开玩笑的间谍函数即可。那不会改变您正在测试的代码调用的功能,因此测试将失败。
所以最终测试应该是:
handleError.test.js:
import * as sentry from '@sentry/browser'; // CHANGED
import handleError from '../handleError';
class ApiError extends Error {
constructor() {
super();
this.name = 'ApiError';
}
}
// added this to remove any spies/mocks after the test
afterEach(() => {
jest.restoreAllMocks();
});
test('When an ApiError is returned with no action type, sentry is notified', () => {
const sampleError = new ApiError();
// added next line
jest.spyOn(sentry, 'captureMessage').mockImplementation(() => {});
handleError(sampleError);
// note the use of `sentry.captureMessage`, which is now a jest spy fn
expect(sentry.captureMessage).toHaveBeenCalledWith('this is an error message.');
});