2011-09-25 39 views
7

我有以下代碼:模擬/存根構造

class Clients 
    constructor : -> 
    @clients = [] 

    createClient : (name)-> 

    client = new Client name 
    @clients.push client 

我與茉莉花BDD像這樣測試它:

describe 'Test Constructor', -> 

    it 'should create a client with the name foo', -> 

    clients = new clients 
    clients.createClient 'Foo' 
    Client.should_have_been_called_with 'Foo' 

    it 'should add Foo to clients', -> 

    clients = new clients 
    clients.createClient 'Foo' 

    expect(clients.clients[0]).toEqual SomeStub 

我在第一次測試中,我要檢查如果構造器是用正確的名字稱呼。在我的第二部分中,我只是想確認是否將新客戶端添加到陣列中。

我正在使用Jasmine BDD,它有一種方法來創建間諜/模擬/存根,但它似乎不可能測試構造函數。所以我正在尋找一種方法來測試構造函數,如果有一種方法我不需要額外的庫,但是我對任何東西都是開放的,那麼它將會很好。

回答

4

我認爲這裏最好的計劃是將新的Client對象創建爲單獨的方法。這將允許您單獨測試Clients類,並使用模擬Client對象。

我掀起了一些示例代碼,但我沒有用茉莉花測試它。希望你能得到它是如何工作的要點:

class Clients 
    constructor: (@clientFactory) -> 
    @clients = [] 

    createClient : (name)-> 
    @clients.push @clientFactory.create name 

clientFactory = (name) -> new Client name 

describe 'Test Constructor', -> 

    it 'should create a client with the name foo', -> 
    mockClientFactory = (name) -> 
    clients = new Clients mockClientFactory 

    clients.createClient 'Foo' 

    mockClientFactory.should_have_been_called_with 'Foo' 

    it 'should add Foo to clients', -> 
    someStub = {} 
    mockClientFactory = (name) -> someStub 
    clients = new Clients mockClientFactory 

    clients.createClient 'Foo' 

    expect(clients.clients[0]).toEqual someStub 

的基本計劃是現在使用一個單獨的函數(clientFactory)來創建新的Client對象。然後這個工廠在測試中被模擬,讓你可以準確地控制返回的內容,並檢查它是否被正確調用。

+0

我很害怕我必須這樣解決它。儘管如此,很好的答案,謝謝。 – Pickels

9

可能在茉莉存根出的構造,語法只是有點出乎意料:

spy = spyOn(window, 'Clients'); 

換句話說,你不踩滅了new方法,你踩滅類在它所處的環境中命名本身,在這種情況下爲window。然後,您可以鏈接andReturn()以返回您選擇的虛假對象,或者使用andCallThrough()來調用真正的構造函數。

參見:Spying on a constructor using Jasmine

+1

如果Clients是閉包上的變量,則這不起作用。 – Zequez

0

我的解決辦法結束了類似@zpatokal

最後我用一個模塊翻過我的應用程序(不是真正的大的應用程序),並從那裏嘲笑。一個問題是,and.callThrough將無法​​正常工作,因爲構造函數將從Jasmine方法中調用,所以我不得不用and.callFake做一些詭計。

在unit.coffee

class PS.Unit 

在units.coffee

class PS.Units 
    constructor: -> 
    new PS.Unit 

而且在規範文件:

Unit = PS.Unit 

describe 'Units', -> 
    it 'should create a Unit', -> 
    spyOn(PS, 'Unit').and.callFake -> new Unit arguments... # and.callThrough() 
    expect(PS.Unit).toHaveBeenCalled() 
0

最近茉莉版本更清晰的解決方案:

window.Client = jasmine.createSpy 'Client' 
clients.createClient 'Foo' 
expect(window.Client).toHaveBeenCalledWith 'Foo'