Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何模拟jQuery.done(),使其正确地使用Jest执行?_Javascript_Reactjs_Jestjs_Enzyme - Fatal编程技术网

Javascript 如何模拟jQuery.done(),使其正确地使用Jest执行?

Javascript 如何模拟jQuery.done(),使其正确地使用Jest执行?,javascript,reactjs,jestjs,enzyme,Javascript,Reactjs,Jestjs,Enzyme,我正在尝试为密码更改模块编写一个单元测试,但是我无法在括号中执行代码。我已经为模块MyAPI编写了一个模拟,模拟代码执行得很好,使用console.logsomething,我可以在控制台中看到输出 但是,我无法让代码在.donefunction数据之后运行。这很可能是因为mock正在用自己的代码替换这些代码 我知道有一种选择是使用像Nock这样的假服务器,但我不想把它变成集成测试,除非我不得不这样做 我正在尝试测试的代码: const MyAPI = require('../../my_api

我正在尝试为密码更改模块编写一个单元测试,但是我无法在括号中执行代码。我已经为模块MyAPI编写了一个模拟,模拟代码执行得很好,使用console.logsomething,我可以在控制台中看到输出

但是,我无法让代码在.donefunction数据之后运行。这很可能是因为mock正在用自己的代码替换这些代码

我知道有一种选择是使用像Nock这样的假服务器,但我不想把它变成集成测试,除非我不得不这样做

我正在尝试测试的代码:

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;