【问题标题】:Bind Mocking Function inside function在函数内部绑定模拟函数
【发布时间】:2017-01-02 16:52:56
【问题描述】:

我正在为我的应用程序编写 QUnit 测试用例。基本上我有三个文件 如下所示。 DataServices.js 具有执行 ajax 调用的 getObjectDetails 方法 获取数据并在回调中传递结果。

Resolver.js 使用 require 加载 DataServices.js。

我正在为 Proxy.resolve 方法编写测试用例,在其中我想避免实际的 api 调用,为此我在 Test.js 中创建了 DataServices 的模拟对象并调用 Resolver 代理解析方法。

我尝试使用 bind ,但仍然指向 DataServices.js 的实际方法,而不是我在 Test.js 中绑定的方法

DataServices.js

define(["module"], function(module) {
"use strict";
 var Details = {
    getObjectDetails :function(param,callback){
       //API AJAX CALL
       // Callback once done
    }
 };
 return {Details : Details }
});

Resolver.js

define(["DataServices"],function(DataServices){
var Proxy= {
  resolve : function(){
  var Details = DataServices.Details ;
     Details.getObjectDetails("xyz", function(result){
         // Do Operation After Result
     });
  }

 };
 return {Proxy:Proxy}
});

Test.js

define(["Resolver.js" ],function(Resolver){

   var DataServices= {
    Details : {
        getObjectDetails : function(undefined,onSuccess, onError) {
            return onSuccess({"X":"Y"});
        }
      }
   };
  Resolver.Proxy.resolve.bind(DataServices);
  Resolver.Proxy.resolve(); // This is still calling DataServices.js Details 
                            // Not the above muck object

});

在简单的程序中,我想调用模拟 z 函数,而不是 x 内部的 z。 如何做到这一点。

var x = {
  z:function(b){
    console.log("Z Actual Function..."+b);
   },
  a : function(){
    this.z(3);
  }
};
var z = function(b){
  console.log("Mock ..."+b)
}

x.a.bind(z);
x.a();

//Z Actual Function...3

但我想要 Mock ...3 打印

【问题讨论】:

    标签: javascript jquery unit-testing qunit


    【解决方案1】:

    第一个问题

    使用.bind创建new function,不会改变原函数中this的值。

    要在您的情况下使用绑定,您可以这样做:

    var mockedA = x.a.bind(z);
    mockedA();
    

    如果您想立即调用函数而不将其分配给变量,您可以改用.call.apply

    例如:

    x.a.call(z); // runs `a()` immediately with `this` set to `z`
    

    第二个问题

    通过将x.a 绑定到z,您将this 的值更改为提供的值(模拟z 函数)。所以在x.a 内部,当你调用this.z(3) 时,你实际上是在尝试调用z.z(3),这是一个不存在的函数,因此会抛出一个TypeError

    可能有更好的方法,但这是回答您问题的方法:

    var x = {
      z:function(b){
        console.log("Z Actual Function..."+b);
      },
      a : function(){
        this.z(3);
      }
    };
    
    var mock = {};
    mock.z = function(b){
      console.log("Mock ..."+b)
    }
    
    // with bind
    var mockXA = x.a.bind(mock);
    mockXA();
    
    // with call
    //x.a.call(mock)

    【讨论】:

    • 我试过 Resolver.Proxy.resolve.bind(DataServices).call() 它仍然是指 DataServices.js getObjectDetails 不是在 test.js 上模拟一个
    • 我对 AMD 风格的模块不是很熟悉,但它不能正常工作的原因可能是因为 Resolver.js 是 not 使用 this 关键字就像你的简化测试用例曾是。 Bind 仅更改 this 关键字的值,但 DataServices 将作为参数提供给模块构造函数。
    • 你说得对,这个关键字不在 DataServices 中,任何方法都可以在不更改代码的情况下破解函数。因为系统正在生产中,我没有灵活更改
    • 您可能会更幸运地直接使用 github.com/ValeriiVasin/requirejs-mock 之类的东西来模拟 DataServices.js 模块。
    猜你喜欢
    • 1970-01-01
    • 2018-12-18
    • 2021-08-27
    • 2019-08-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多