【问题标题】:How to write mock for 3rd party library with nested functions (javascript, jasmine)如何使用嵌套函数(javascript,jasmine)为 3rd 方库编写模拟
【发布时间】:2016-06-25 20:46:24
【问题描述】:

我是 TDD 新手,我正在尝试编写使用第三方库(跨平台移动开发)的可测试代码。我想进行测试以仅检查我们的业务逻辑。不用担心它们的实施。

他们的更多库仅在本机包装器中公开。由于使用 js 作为开发语言,我想使用 jasmine 进行测试并运行测试以仅在浏览器中检查我的业务逻辑。

以下是我想在测试时忽略/模拟的方法模式。

com.companyname.net.checkInternetAvailable(url) 

com.companyname.store.getValue(key)

com.companyname.someother.name(whateverObj, callback) etc.,

目前,我创建了一个新的mocks.js 文件,我只是在其中写了

var com = {
    "net":{},
    "store":{},
    "someother":{}
}

com.net.checkInternetAvailable = function(url){
    //TODO: fix this!
    return true;
}

我对代码中的所有方法都执行相同的操作。我尝试使用 Jasmine SpyOn(com.net, "checkInternetAvailable").and.returnValue(true) 而不是定义所有方法。这种方法的问题是我必须定义所有使用SpyOn 的方法。

有没有更简单的方法来做到这一点?推荐的方法是什么?

【问题讨论】:

  • 嗨@palaniraja。这些第三方模块是如何包含的?你的代码中有整个对象吗?
  • 是的@Tokimon 当我在本机包装器中运行它们时,我拥有整个对象。我相信他们在后台运行 webkit 引擎来执行代码。但我的要求。只是用我的存根方法模拟所有调用,以检查方法调用的顺序并验证所有预期的方法都被调用了。
  • 嗨@palaniraja,通常我会循环对象和子对象上的所有属性,并用你的function() { return true; }(或sinon 存根)存根每个属性,但这只有在你不这样做时才有效关心哪一个被调用,只是希望它们都返回 true。如果您需要检查是否调用了特定方法,那么您需要在测试中指定您希望调用哪些方法。

标签: javascript unit-testing mocking jasmine tdd


【解决方案1】:

您可以采取的一种方法是使用Sinon javascript 测试库来存根第三方库方法。然后可以设置这些存根方法来模拟使用实际第三方库难以重现的结果。然后,您的被测系统 (SUT) 可以在您的 Jasmine 测试中使用这些存根方法。

我在这里写了一个人为的例子:

https://jsfiddle.net/Fresh/uf8owzdb/

代码如下:

// A module which has methods you want to stub
Net = (function() {

  // Constructor
  function Net() {
  }

  Net.prototype.checkInternetAvailable = function(url) {
    return true;
  };

  return Net;

})();

// A method which is dependent on the Net module
var methodWhichUsesNet = function(net) {
    return net.checkInternetAvailable();
};

// Stub the method behaviour using Sinon javascript framework.
// For the test, get it to return false instead of true.
var net = new Net();
var expectedResult = false;
sinon.stub(net, "checkInternetAvailable").returns(expectedResult);

// Assert method behaviour using a Jasmine test
describe("Net test suite", function() {
  it("methodWhichUsesNet should return expected result", function() {
    expect(methodWhichUsesNet(net)).toBe(expectedResult);
  });
});

请注意,建议stub 第三方方法,因为您想准确控制它们应该返回的内容,因为您知道您的代码正在使用哪些方法。或者,如果您还想验证这些方法是否由使用它们的方法调用,您可以mock 这些第三方方法。您可以使用例如:

存根整个第三方对象方法
var stub = sinon.stub(obj);

但是我建议不要这样做,因为这意味着测试不会那么明确,即您无法确定存根方法的行为方式,而显式存根意味着您可以完全控制它们的行为。

【讨论】:

  • sinon.stub(obj) 是否也存根所有更深层次的功能(比如 3 级)com.domain.net.isnetworkavailable?
  • Sinon 将存根该对象中的方法,所以实际上它会隐式存根所有更深层次的函数。
  • 但是,就像我在回答中所说的那样,我不会推荐这种方法,因为它会使测试变得不那么明确并且更难理解正在测试的行为。
  • 此答案是否有助于解决您的问题?
猜你喜欢
  • 2021-06-18
  • 1970-01-01
  • 2017-05-29
  • 1970-01-01
  • 1970-01-01
  • 2012-09-13
  • 1970-01-01
  • 2020-03-21
相关资源
最近更新 更多