轻松清理sinon存根


134

有没有一种方法可以轻松重置所有可与Mocha的beforeEach块完美配合的s​​inon间谍模拟和存根。

我看到沙盒是一个选项,但是我看不到如何使用沙盒

beforeEach ->
  sinon.stub some, 'method'
  sinon.stub some, 'mother'

afterEach ->
  # I want to avoid these lines
  some.method.restore()
  some.other.restore()

it 'should call a some method and not other', ->
  some.method()
  assert.called some.method

Answers:


304

Sinon通过使用箱提供了此功能,可以使用以下两种方式:

// manually create and restore the sandbox
var sandbox;
beforeEach(function () {
    sandbox = sinon.sandbox.create();
});

afterEach(function () {
    sandbox.restore();
});

it('should restore all mocks stubs and spies between tests', function() {
    sandbox.stub(some, 'method'); // note the use of "sandbox"
}

要么

// wrap your test function in sinon.test()
it("should automatically restore all mocks stubs and spies", sinon.test(function() {
    this.stub(some, 'method'); // note the use of "this"
}));

6
@CamJackson进行异步测试后,您需要使用第一种方法,否则sinon在测试完成执行之前清除其存根。
keithjgrant 2014年

3
如果您使用的是sinon> 5.0,请阅读以下内容。现在有一种更简单的方法:stackoverflow.com/a/55251560/4464702
RAnders00 '19

53

先前的答案建议使用sandboxes来完成此操作,但根据文档

从sinon@5.0.0开始,sinon对象是默认的沙箱。

这意味着清理存根/模拟/间谍现在变得很容易:

var sinon = require('sinon');

it('should do my bidding', function() {
    sinon.stub(some, 'method');
}

afterEach(function () {
    sinon.restore();
});

10
这是在2018
Nick Cox

1
甚至更加eter谐:afterEach(sinon.restore)
杰姆

我认为这样做会更好,因为显式沙箱会产生不必要的复杂性。您是否真的需要几个单独的沙箱,并且具有相同对象的不同模拟?可能不是。
盖尔曼

13

@keithjgrant答案的更新。

从版本V2.0.0起,sinon.test方法已被转移到一个独立的sinon-test模块。要使旧的测试通过,您需要在每个测试中配置此额外的依赖项:

var sinonTest = require('sinon-test');
sinon.test = sinonTest.configureTest(sinon);

另外,您可以不sinon-test使用沙箱,而使用沙箱

var sandbox = sinon.sandbox.create();

afterEach(function () {
    sandbox.restore();
});

it('should restore all mocks stubs and spies between tests', function() {
    sandbox.stub(some, 'method'); // note the use of "sandbox"
} 

1
或者,您可以只使用sinon-test包并像以前一样继续执行代码:-D
oligofren

10

您可以使用sinon库的作者在博客文章(日期为2010年5月)中说明的sinon.collection。

sinon.collection API已更改,并且使用它的方法如下:

beforeEach(function () {
  fakes = sinon.collection;
});

afterEach(function () {
  fakes.restore();
});

it('should restore all mocks stubs and spies between tests', function() {
  stub = fakes.stub(window, 'someFunction');
}

6

restore()仅恢复存根功能的行为,但不重置存根的状态。您必须将测试包装在一起sinon.test并使用,this.stub或者单独调用reset()存根


6

如果您想要一个具有sinon的设置,请在所有测试中始终将其重置:

在helper.js中:

import sinon from 'sinon'

var sandbox;

beforeEach(function() {
    this.sinon = sandbox = sinon.sandbox.create();
});

afterEach(function() {
    sandbox.restore();
});

然后,在您的测试中:

it("some test", function() {
    this.sinon.stub(obj, 'hi').returns(null)
})

3

请注意,使用qunit代替mocha时,需要将它们包装在模块中,例如

module("module name"
{
    //For QUnit2 use
    beforeEach: function() {
    //For QUnit1 use
    setup: function () {
      fakes = sinon.collection;
    },

    //For QUnit2 use
    afterEach: function() {
    //For QUnit1 use
    teardown: function () {
      fakes.restore();
    }
});

test("should restore all mocks stubs and spies between tests", function() {
      stub = fakes.stub(window, 'someFunction');
    }
);

3
qunit 2切换到beforeEachafterEach。该setupteardown方法将被弃用。
凯文·布洛维

0

创建一个沙箱,将其用作所有间谍,存根,模拟和假货的黑匣子容器。

您所要做的就是在第一个describe块中创建一个沙箱,以便可以在所有测试用例中访问它。一旦完成所有测试用例,就应该释放原始方法,并sandbox.restore()在afterEach挂钩中使用该方法清理存根 ,以便在运行时释放保留的资源afterEach测试用例通过或失败。

这是一个例子:

 describe('MyController', () => {
    //Creates a new sandbox object
    const sandbox = sinon.createSandbox();
    let myControllerInstance: MyController;

    let loginStub: sinon.SinonStub;
    beforeEach(async () => {
        let config = {key: 'value'};
        myControllerInstance = new MyController(config);
        loginStub = sandbox.stub(ThirdPartyModule, 'login').resolves({success: true});
    });
    describe('MyControllerMethod1', () => {
        it('should run successfully', async () => {
            loginStub.withArgs({username: 'Test', password: 'Test'}).resolves();
            let ret = await myControllerInstance.run();
            expect(ret.status).to.eq('200');
            expect(loginStub.called).to.be.true;
        });
    });
    afterEach(async () => {
        //clean and release the original methods afterEach test case at runtime
        sandbox.restore(); 
    });
});
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.