2016-12-06 87 views
1

當試圖使用Jest的.toHaveBeenCalledWith()方法測試傳遞給該函數的參數時,如果使用ImmutableJS庫處理不可變數據結構,則測試失敗。測試失敗,類似這樣的消息:使用不可變數據結構時,Jest模擬函數參數不匹配

Expected mock function to have been called with: 
    [{"foo": true, "bar": "baz"}] 
But it was called with: 
    [{"foo": true, "bar": "baz"}] 

測試類似於這樣:

const expectedArgs = Map({ 
    foo: true, 
    bar: 'baz' 
}); 

const foo = jest.fn(); 
bar(); 
expect(foo).toHaveBeenCalledWith(expectedArgs); 

而類似這樣的功能:

const bar =() => { 
    const baz = Map({}); 
    const bazModified = baz.set('foo', true).set('bar', 'baz'); 
    foo(bazModified); 
} 

我意識到,如果我以這種方式傳遞參數一切正常:

const bar =() => { 
    const baz = Map({ 
    foo: true, 
    bar: 'baz' 
    }); 
    foo(baz); 
} 

問題是,這是我的函數的邏輯大大簡化,我不得不使用.set來構造對象。有沒有人知道爲什麼.set方法無法正確評估?

回答

2

所以你的測試失敗了,因爲toHaveBeenCalledWith只有在實體的實例完全相同時纔會通過。它類似於以下,這也將失敗:

const expectedArgs = Map({ 
    foo: true, 
    bar: 'baz' 
}); 

const input = Map({ 
    foo: false, 
    bar: 'baz' 
}); 

const result = input.set('foo', true); 

expect(result).toBe(expectedArgs); 

此,在另一方面,沒有工作:

expect(result).toEqual(expectedArgs); 

由於執行了深刻的相等。

因爲baz.set('foo', true)將始終返回一個新的實例(這是使用不可變數據的要點),所以您無法測試與toHaveBeenCalledWith的相等性。

我不認爲有一種方式讓toHaveBeenCalledWith表現得像toEqual,所以我猜要走的路是手動測試與toEqual模擬電話:

const expectedArgs = Map({ 
    foo: true, 
    bar: 'baz' 
}); 

const foo = jest.fn(); 
bar(); 
// foo.mock.calls[0][0] returns the first argument of the first call to foo 
expect(foo.mock.calls[0][0]).toEqual(expectedArgs); 

參見toBe的文件, 和mock calls