Javascript 如何模拟jQuery.done(),使其正确地使用Jest执行?
我正在尝试为密码更改模块编写一个单元测试,但是我无法在括号中执行代码。我已经为模块MyAPI编写了一个模拟,模拟代码执行得很好,使用console.logsomething,我可以在控制台中看到输出 但是,我无法让代码在.donefunction数据之后运行。这很可能是因为mock正在用自己的代码替换这些代码 我知道有一种选择是使用像Nock这样的假服务器,但我不想把它变成集成测试,除非我不得不这样做 我正在尝试测试的代码:Javascript 如何模拟jQuery.done(),使其正确地使用Jest执行?,javascript,reactjs,jestjs,enzyme,Javascript,Reactjs,Jestjs,Enzyme,我正在尝试为密码更改模块编写一个单元测试,但是我无法在括号中执行代码。我已经为模块MyAPI编写了一个模拟,模拟代码执行得很好,使用console.logsomething,我可以在控制台中看到输出 但是,我无法让代码在.donefunction数据之后运行。这很可能是因为mock正在用自己的代码替换这些代码 我知道有一种选择是使用像Nock这样的假服务器,但我不想把它变成集成测试,除非我不得不这样做 我正在尝试测试的代码: const MyAPI = require('../../my_api
const MyAPI = require('../../my_api.js');
submitChangePasswordFormEvent(event) {
const self = this;
const params = {};
event.preventDefault();
event.stopPropagation();
params.current_password = this.refs.current_password.getValue();
params.passwordFirst = this.refs.passwordFirst.getValue();
params.passwordSecond = this.refs.passwordSecond.getValue();
MyAPI.my_api('/api/change_password/', params)
.done(function (data) {
// This code i would like to run but can't
const elem = <Success>{t(['settings',
'passwords_changed'])}</Success>;
self.setState({ pwerror: null, pwsuccess: elem });
self.refs.current_password.value = '';
self.refs.password1.value = '';
self.refs.password2.value = '';
})
.error(function (errors) {
// This code i would like to run but can't
let msg = '';
$.each(errors.responseJSON, function (k, v) {
msg += v;
});
msg = <Error>{msg}</Error>;
self.setState({ pwerror: msg, pwsuccess: null });
});
}
和Jest设置脚本:
const jqueryMock = {
ajax: function (argument) {
return {done: function (data) {
return {error: function (errors) {
return "success";
}}}}
}}
global.$ = jqueryMock;
您希望执行.done或.error方法,但不希望实际发出请求。顺便说一句,我不知道.error方法只是.fail?然后我会做以下几件事:
全局模拟jQuery
在工作目录顶层的_mocks__目录中为jquery创建全局模拟:
//__mocks_;/jquery.js:
const jQ=jest.requireActualjquery;
const ajax=jest.fn=>{
返回jQ.Deferred;
};
导出常量$={
…jQ,//我们不希望完全模拟jQuery,我们可能希望更改$。延迟状态
AJAX
};
导出默认值$;
通过将jquery.js放在_mocks_________________________________________
使用此设置,您可以只运行代码而不发出实际请求,但通常运行.done和.error方法以及注册的回调
Mock.done和.fail方法
如果不想在.done或.fail中执行注册的回调,则需要手动模拟它们,而不是返回jQ.Deferred,返回一个带有jest mock的普通javascript对象
在一个特定的测试用例中,您肯定不希望这样。完成/。错误调用您注册的回调:
//通过返回该值,我们能够以$.ajax/api、params.done.fail的方式进行链接
常数jqXHR={
完成:jest.fn.mockImplementationfunction{
归还这个;
},
失败:jest.fn.mockImplementationfunction{
归还这个;
},
//还有一些要模拟的$.Deferred方法
};
//用我们的自定义实现覆盖来自_mocks_;/jquery.js的全局$.ajax模拟实现
$.ajax.mockImplementation=>jqXHR
模拟成功或错误
如果要在特定测试用例中再次模拟成功或错误,请覆盖全局模拟实现:
为了成功:
//成功
const dfd=$。递延;
$.ajax.mockImplementation=>{
return dfd.resolvesuccess;//这是您的done回调将作为参数接收的内容
};
对于错误:
//成功
const dfd=$。递延;
$.ajax.mockImplementation=>{
return dfd.rejecterror;//这是失败回调将作为参数接收的内容
};
请注意,断言调用了/未调用.done或.fail是没有意义的,因为它们总是被调用,因为它们注册了您放在其中的回调。只有当$.Deferred解析或拒绝特定的已注册回调时,才会执行该回调,然后可以对其进行测试
为了更好地进行可测试性w.r.t单元测试,您应该将匿名函数从.done/.error中剔除。由于JavaScript很奇怪,不像我更喜欢的python,所以您无法轻松地模拟测试模块中的特定函数。因此,您需要将它们放在一个专用模块中,并完全模拟这个模块。然后,您可以断言在成功或错误情况下调用了它们
我花了一段时间才弄明白如何正确处理jquery的模拟,所以我想在这里分享我的经验。希望这有帮助……这能回答您的问题吗?
const jqueryMock = {
ajax: function (argument) {
return {done: function (data) {
return {error: function (errors) {
return "success";
}}}}
}}
global.$ = jqueryMock;