2014-10-31 51 views
1

這是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

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屬性來窺探它。

我希望用beforeEachrequire('foo.js')將覆蓋Foo對象,並下試不知道以前的更改對象。

顯而易見的解決方案是存儲對前一個屬性狀態的引用並在測試後恢復它,例如,

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) {}; 
}; 

然後在每次測試之前建立一個新的實例:

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

不理想,但因爲這會影響庫的API。

回答

1

因此,sinon修復了內置的間諜/存根/嘲諷。最好讓sinon自行清理,而不是嘗試手動實現自己的清理代碼。摩卡,甚至有mocha-sinon這將爲你做清理。 mocha-sinon文檔還解釋瞭如何使用sinon沙箱來跟蹤需要清理和清理的內容,但是如果您在mocha測試代碼中使用mocha-sinon並執行this.sinon,則沙箱創建和清理將自動進行您。

var sinon = require('sinon'); 

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

afterEach(function(){ 
    this.sinon.restore(); 
}); 
+0

sinon如何恢復'Foo.get'的屬性值? – Gajus 2014-10-31 10:49:10

+0

使用此語法:'this.sinon.spy(Foo,「get」)'。這樣,因爲它知道字符串屬性名稱,它可以將它恢復到未加密版本。 – 2014-10-31 10:50:35

+0

這很有道理。 – Gajus 2014-10-31 10:51:08

相關問題