测试一个函数是否在另一个函数 Jest 中被调用
Testing if a function is called inside another function Jest
我正在编写 Redux 操作来完成单元测试,但在测试中模拟函数调用时遇到问题。我相信我已经正确地模拟了 completeRegistration
,通过导入它在其中声明的模块,然后从模块引用中模拟函数,但是 Jest 说尽管控制台日志语句确认 verified.data.success
条件为true
.
知道我做错了什么吗?谢谢
auth.js
export const verifyEmail = ({
originalCode,
confirmCode,
token
}) => async dispatch => {
try {
const body = JSON.stringify({
originalCode,
confirmCode,
registering: true
});
const verified = await axios.post("/api/email/verify", body, config);
if (verified.data.success) {
console.log("Success!") // logs "Success!"
completeRegistration(token); // test is to find out if this function gets called
} else {
return { msg: "Code did not match, please try again" };
}
} catch (err) {
dispatch({
type: REGISTER_FAILED
});
}
};
auth.test.js
import * as auth from "../../actions/auth";
const originalCompleteReg = auth.completeRegistration;
describe("verifyEmail action", () => {
let verifyData;
beforeEach(() => {
verifyData = {
originalCode: "1234546",
confirmCode: "1234546",
token: "87618g1u8ojb98k3jb12i3kwdbcjwvbbi92ueg29eubv" // fake data :p
};
auth.completeRegistration = jest.fn(() => auth.completeRegistration);
moxios.install();
});
afterEach(() => {
auth.completeRegistration = originalCompleteReg;
moxios.uninstall();
});
it("calls completeRegistration function if successful", async () => {
moxios.wait(() => {
const request = moxios.requests.mostRecent();
request.respondWith({
status: 200,
response: { success: true }
});
});
const store = mockStore({ payload: {} });
await store.dispatch(auth.verifyEmail(verifyData));
expect(auth.completeRegistration).toBeCalled();
});
});
输出
verifyEmail action › calls completeRegistration function if successful
expect(jest.fn()).toBeCalled()
Expected number of calls: >= 1
Received number of calls: 0
问题是您不是在模拟 auth
模块中 verifyEmail
使用的 completeRegistration
的内部值,而是模拟导出的值。
当您导入一个模块时,您会得到一个引用该模块函数的对象。如果您覆盖所需模块中的值,您自己的引用将被覆盖,但实现会保留原始引用。
因此,在您的情况下,如果您在测试文件中调用 auth.completeRegistration
,您将调用模拟版本。但是当调用auth.verifyEmail
(内部调用completeRegistration
)时,它引用的completeRegistration
不是你覆盖的版本。
我认为您不应该测试您的 completeRegistration
方法是否被调用(毕竟,那是一个实现细节)。相反,您应该检查您的方法是否按预期运行(即行为 completeRegistration
具有,无论是重定向到另一个页面、执行附加请求、保存 cookie 等)。因此,您将嘲笑 completeRegistration
中使用的 API 而不是方法本身。
话虽这么说,如果您想检查 completeRegistration
是否被调用,您还有几个选择。
使用babel rewire插件
您必须安装该插件并将其添加到您的 babel 配置中。完成后,您的测试将如下所示:
import AuthModule from '../../actions/auth';
import * as auth from '../../actions/auth';
describe('verifyEmail action', () => {
let verifyData;
beforeEach(() => {
verifyData = {
originalCode: '1234546',
confirmCode: '1234546',
token: '87618g1u8ojb98k3jb12i3kwdbcjwvbbi92ueg29eubv'
};
moxios.install();
});
afterEach(() => {
moxios.uninstall();
});
it('calls completeRegistration function if successful', async () => {
moxios.wait(() => {
const request = moxios.requests.mostRecent();
request.respondWith({
status: 200,
response: { success: true }
});
});
const mockFn = jest.fn();
AuthModule.__Rewire__('completeRegistration', mockFn);
const store = mockStore({ payload: {} });
await store.dispatch(auth.verifyEmail(verifyData));
expect(mockFn).toHaveBeenCalled();
AuthModule.__ResetDependency__('completeRegistration');
});
});
将不同文件中的函数分开
您可以为 completeRegistration
函数创建一个单独的模块。这样,由于您的 auth.js 必须导入模块,您将能够使用 jest.mock
功能模拟模块。
我正在编写 Redux 操作来完成单元测试,但在测试中模拟函数调用时遇到问题。我相信我已经正确地模拟了 completeRegistration
,通过导入它在其中声明的模块,然后从模块引用中模拟函数,但是 Jest 说尽管控制台日志语句确认 verified.data.success
条件为true
.
知道我做错了什么吗?谢谢
auth.js
export const verifyEmail = ({
originalCode,
confirmCode,
token
}) => async dispatch => {
try {
const body = JSON.stringify({
originalCode,
confirmCode,
registering: true
});
const verified = await axios.post("/api/email/verify", body, config);
if (verified.data.success) {
console.log("Success!") // logs "Success!"
completeRegistration(token); // test is to find out if this function gets called
} else {
return { msg: "Code did not match, please try again" };
}
} catch (err) {
dispatch({
type: REGISTER_FAILED
});
}
};
auth.test.js
import * as auth from "../../actions/auth";
const originalCompleteReg = auth.completeRegistration;
describe("verifyEmail action", () => {
let verifyData;
beforeEach(() => {
verifyData = {
originalCode: "1234546",
confirmCode: "1234546",
token: "87618g1u8ojb98k3jb12i3kwdbcjwvbbi92ueg29eubv" // fake data :p
};
auth.completeRegistration = jest.fn(() => auth.completeRegistration);
moxios.install();
});
afterEach(() => {
auth.completeRegistration = originalCompleteReg;
moxios.uninstall();
});
it("calls completeRegistration function if successful", async () => {
moxios.wait(() => {
const request = moxios.requests.mostRecent();
request.respondWith({
status: 200,
response: { success: true }
});
});
const store = mockStore({ payload: {} });
await store.dispatch(auth.verifyEmail(verifyData));
expect(auth.completeRegistration).toBeCalled();
});
});
输出
verifyEmail action › calls completeRegistration function if successful
expect(jest.fn()).toBeCalled()
Expected number of calls: >= 1
Received number of calls: 0
问题是您不是在模拟 auth
模块中 verifyEmail
使用的 completeRegistration
的内部值,而是模拟导出的值。
当您导入一个模块时,您会得到一个引用该模块函数的对象。如果您覆盖所需模块中的值,您自己的引用将被覆盖,但实现会保留原始引用。
因此,在您的情况下,如果您在测试文件中调用 auth.completeRegistration
,您将调用模拟版本。但是当调用auth.verifyEmail
(内部调用completeRegistration
)时,它引用的completeRegistration
不是你覆盖的版本。
我认为您不应该测试您的 completeRegistration
方法是否被调用(毕竟,那是一个实现细节)。相反,您应该检查您的方法是否按预期运行(即行为 completeRegistration
具有,无论是重定向到另一个页面、执行附加请求、保存 cookie 等)。因此,您将嘲笑 completeRegistration
中使用的 API 而不是方法本身。
话虽这么说,如果您想检查 completeRegistration
是否被调用,您还有几个选择。
使用babel rewire插件
您必须安装该插件并将其添加到您的 babel 配置中。完成后,您的测试将如下所示:
import AuthModule from '../../actions/auth';
import * as auth from '../../actions/auth';
describe('verifyEmail action', () => {
let verifyData;
beforeEach(() => {
verifyData = {
originalCode: '1234546',
confirmCode: '1234546',
token: '87618g1u8ojb98k3jb12i3kwdbcjwvbbi92ueg29eubv'
};
moxios.install();
});
afterEach(() => {
moxios.uninstall();
});
it('calls completeRegistration function if successful', async () => {
moxios.wait(() => {
const request = moxios.requests.mostRecent();
request.respondWith({
status: 200,
response: { success: true }
});
});
const mockFn = jest.fn();
AuthModule.__Rewire__('completeRegistration', mockFn);
const store = mockStore({ payload: {} });
await store.dispatch(auth.verifyEmail(verifyData));
expect(mockFn).toHaveBeenCalled();
AuthModule.__ResetDependency__('completeRegistration');
});
});
将不同文件中的函数分开
您可以为 completeRegistration
函数创建一个单独的模块。这样,由于您的 auth.js 必须导入模块,您将能够使用 jest.mock
功能模拟模块。