简体   繁体   English

使用Sinon.js存入模拟方法

[英]Stubbing a mock's method with Sinon.js

I'm having trouble using a mock to replace a dependency of my class when testing, using Sinon.js and Buster.js. 我在使用Sinon.js和Buster.js进行测试时,无法使用模拟来替换类的依赖项。

I'm testing class B, which has a dependency on class A. I use Sinon.js to create a mock object of class A, and pass it into an instance of class B. In my test I call the doSomething method of object B, which then calls the getData method of object A. (Though the getData method is actually on A's prototype, not A itself). 我正在测试依赖于类A的类B。我使用Sinon.js创建类A的模拟对象,并将其传递到类B的实例中。在测试中,我调用对象B的doSomething方法,然后调用对象A的getData方法。(尽管getData方法实际上是在A的原型上,而不是A本身)。

But when I run the test I get the error: 但是,当我运行测试时,我得到了错误:

TypeError: a.getData is not a function

If I try and stub the getData method of A's prototype, then I get the error: 如果我尝试对A的原型的getData方法存根,则会收到错误消息:

TypeError: Attempted to wrap getData which is already stubbed

The error occurs on the line where I'm setting mock_A.expects('getData') . 该错误发生在我设置mock_A.expects('getData') This is the classes and test I'm running: 这是我正在运行的类和测试:

function A(){};
A.prototype = {
    "getData" : function(oDataToGet, cb) {
        var aData = ['someData'];
        cb(aData);
    }
}
function B() {
    var a;
    this.setA = function(oA){
        a = oA;
    };
    this.doSomething = function(oObj){
        a.getData({}, function(aData){if(!aData){throw new Error('No data');} oObj.data = aData[0];});
    }
}


var oB, assert = buster.referee.assert;
buster.testCase('myTest', {
    "setUp" : function()
    {
        oB = new B();
    },
    "test_Mock" : function()
    {
        var mock_A = sinon.mock(new A());
            oB.setA(mock_A);
    //        sinon.stub(A.prototype, 'getData').callsArgWith(1, ['hi']);
        mock_A.expects('getData')
            .withArgs({})
            .once();
        var oTestObj = {};
        oB.doSomething(oTestObj)
        mock_A.verify();
    }
});

Edit 2016-03-16 to add: A workaround is to use a stubbed instance rather than a mock, and then set the method you need to check to an expectation: 编辑2016-03-16以添加:一种解决方法是使用存根实例而不是模拟实例,然后将需要检查的方法设置为期望值:

var stubbed_A = sinon.createStubInstance(A);
stubbed_A.getData = sinon.expectation.create('getData')
    .withArgs({})
    .once();
oB.setA(stubbed_A);
var oTestObj = {};
oB.doSomething(oTestObj);
stubbed_A.getData.verify();

There is a difference between sinonJS and other mocking frameworks (like Mockito, jMock etc.) that creates this misunderstanding. sinonJS与其他产生这种误解的模拟框架(例如Mockito,jMock等)之间存在差异。 In most mocking frameworks, you create the mocked dependency and inject it in the object-to-be-tested (SUT), as you did: 在大多数模拟框架中,您可以像创建模拟对象一样创建模拟的依赖项并将其注入到待测试对象(SUT)中:

var mock_A = sinon.mock(new A());
oB.setA(mock_A);

However, in sinonJS, you have to inject the original object and use the generated mock object to assign expectations over the original one. 但是,在sinonJS中,您必须注入原始对象,并使用生成的模拟对象为原始对象分配期望。 So, if you change the previous 2 lines with the following, your test works as expected: 因此,如果使用以下内容更改前两行,则测试将按预期进行:

var a = new A();
var mock_A = sinon.mock(a);
oB.setA(a);

Stubs are more appropriate, when we want to control the behaviour of a dependency of the object we are testing. 当我们想控制我们正在测试的对象的依赖项的行为时,存根更为合适。 Mocks are more appropriate, when we want to ensure that a specific event will happen on the dependency of the object we are testing (via expectations). 当我们要确保特定事件将发生在我们测试的对象的依赖关系上(通过期望)时,模拟更合适。 So, in this case, a mock object would be more suitable than a stub, as in your first attempt. 因此,在这种情况下,就像您的第一次尝试一样,模拟对象比存根更合适。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM