[英]Unable to stub a function using Sinon
我有一個Redux動作,它本身會調度其他兩個動作。 每個操作均從導入的函數中檢索。 一個來自本地模塊,另一個來自外部庫。
import { functionA } from './moduleA';
import { functionB } from 'libraryB';
export function myAction() {
return (dispatch) => {
dispatch(functionA());
...
dispatch(functionB());
}
}
在我的測試中,我使用sinon
沙箱對功能進行了測試,但是只有兩個測試通過了。 我希望所有三個都通過。
import * as A from './moduleA';
import * as B from 'libraryB';
describe(__filename, async () => {
it('Calls 2 other actions', () => {
sandbox = sinon.sandbox.create();
const dispatch = sandbox.stub();
sandbox.stub(A, 'functionA');
sandbox.stub(B, 'functionB');
await myAction()(dispatch);
// passes
expect(dispatch.callCount).to.equal(2);
//passes
expect(A.functionA).to.have.been.called();
// fails
expect(B.functionB).to.have.been.called();
});
});
最后的期望因錯誤而失敗:
TypeError:[Function:functionB]不是間諜,也不是間諜!
當我將功能輸出到控制台時,我得到了這一點,這似乎與Babel導入導出導出的方式有關(將ES6重新導出的值包裝到Getter中 )。 這些功能可以實時運行,只是不在測試中。
{ functionA: [Function: functionA] }
{ functionB: [Getter] }
我試過使用stub.get(getterFn)
但這只是給我錯誤:
TypeError:無法重新定義屬性:fetchTopicAnnotations
您是否嘗試過命名存根? 您的代碼有點怪異。 在測試中的任何時候,您都不是指存根。
import * as A from './moduleA';
import * as B from 'libraryB';
describe(__filename, async () => {
it('Calls 2 other actions', () => {
sandbox = sinon.sandbox.create();
const dispatch = sandbox.stub();
const functionAStub = sandbox.stub(A, 'functionA');
const functionBStub = sandbox.stub(B, 'functionB');
await myAction()(dispatch);
// passes
expect(dispatch.callCount).to.equal(2);
//passes
expect(functionAStub.called).toBe(true);
// fails
expect(functionBStub.called).toBe(true);
});
});
很難說是100%,但是看來該模塊正在導入,因此在進行測試存根之前直接引用了該功能。 Sinon將有效地替換導出對象上的函數,但另一個模塊將首先導入並獲得對實函數的引用,替換它不會導致重新加載。
您可以對其進行試驗並通過將其更改為以下模塊來證明這一點:
import * as A from './moduleA';
import * as B from 'libraryB';
export function myAction() {
return (dispatch) => {
dispatch(A.functionA());
...
dispatch(B.functionB());
}
}
從本質上講,這將在調用時查找對functionA / functionB的引用,這將使您可以用存根替換它們。
如果您發現這很重要,並且想要保留原始格式,那么我相信您需要使用另一個名為proxyquire
庫,它將有效地使您存根要導入的整個模塊。
您的測試功能最終看起來像這樣:
import * as proxyquire from 'proxyquire'
// import * as A from './moduleA'
// import * as B from 'libraryB'
describe(__filename, async () => {
const A = {}
const B = {}
const functionAStub = sandbox.stub(A, 'functionA')
const functionBStub = sandbox.stub(B, 'functionB')
const { myAction } = proxyquire('./myAction', {
'./moduleA': A,
'libraryB': B
})
...
})
在需要該模塊時,直到您調用proxyquire時,該模塊才會被導入,它將使用存根模塊而不是真實模塊。
然后,您可以按預期從測試中引用這些存根。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.