如何确保testing对象属性的更改不会传播到其他testing用例?

这是foo.js

 var Foo; Foo = function () { var foo = {}; foo.get = function (url) { // [..] return Foo.get(url); }; return foo; }; Foo.get = function (url) {}; module.exports = Foo; 

这是foo.js一个testing用例:

 var expect = require('chai').expect, sinon = require('sinon'); describe('foo', function () { var Foo, foo; beforeEach(function () { Foo = require('foo.js'); foo = Foo(); }); describe('.get(url)', function () { it('passes the call to Foo.get(url)', function () { var spy = sinon.spy(); // We are going to spy on Foo.get: Foo.get = spy; foo.get('http://'); // [..] }); it('does something else', function () { foo.get('http://'); // Here Foo.get persists to refer to an instance of sinon.spy. // How to make sure that the tests are indepeondent? }); }); }); 

我已经覆盖了Foo.get属性来监视它。

我期望使用beforeEach require('foo.js')将覆盖Foo对象,并使下一个testing不知道以前对对象的更改。

显而易见的解决scheme是存储对之前属性状态的引用,并在testing之后将其恢复,例如

 it('passes the call to Foo.get(url)', function () { var spy = sinon.spy(), Fooget = Foo.get; // We are going to spy on Foo.get: Foo.get = spy; foo.get('http://'); // [..] Foo.get = Fooget; }); 

但是,这种方法很容易出错。

这样做的一个方法是重写模块并将其变成构造函数:

 module.exports = function () { var Foo; Foo = function () { var foo = {}; foo.get = function (url) { // [..] return Foo.get(url); }; return foo; }; Foo.get = function (url) {}; }; 

然后在每次testing之前构build一个新的实例:

 describe('foo', function () { var Foo, foo; beforeEach(function () { Foo = require('foo.js')(); foo = Foo(); }); describe('.get(url)', function () { // [..] }); }); 

虽然不理想,因为这影响了图书馆的API。

所以sinon已经修复了内置的间谍/存根/嘲讽。最好让sinon自己清理,而不是试图手动实现自己的清理代码。 用摩卡,甚至还有摩卡咖啡,它会为你做清理。 mocha-sinon文档还解释了如何使用sinon沙箱来跟踪需要清理和清理的内容,但是如果您在mochatesting代码中使用mocha-sinon并执行此操作, this.sinon发生沙盒创build和清理自动为你。

 var sinon = require('sinon'); beforeEach(function() { this.sinon = sinon.sandbox.create(); }); afterEach(function(){ this.sinon.restore(); });