何が起こると思いましたか?
クラスにモックを作成し、 withArgs
を使用してその関数のいずれかの動作を制御しようとすると、例外がスローされます。 withArgs
複数の呼び出しを使用する場合にのみ発生します。
実際に何が起こるか
再現する方法再現可能な例
クラスC
を宣言したと仮定します。
class C {
static foo(arg1, arg2) {return 'foo';}
}
C
モックを使用してfoo
の動作を制御しようとしています:
it('test withArgs mock', () => {
let CMock = sinon.mock(C);
let fooStub = CMock.expects('foo');
fooStub.withArgs('a', 'b').returns(1);
fooStub.withArgs('c', 'd').returns(2);
expect(fooStub('a', 'b')).toEqual(1);
expect(fooStub('c', 'd')).toEqual(2);
CMock.restore();
});
これは次の例外をスローします:
ExpectationError:fooが間違った引数を受け取りました["a"、 "b"]、予期された["c"、 "d"]
Object.failで(node_modules / sinon / lib / sinon / mock-expectation.js:281:25)
関数で。(node_modules / sinon / lib / sinon / mock-expectation.js:182:33)
Array.forEach(ネイティブ)で
Function.verifyCallAllowed(node_modules / sinon / lib / sinon / mock-expectation.js:175:27)で
Function.invokeで(node_modules / sinon / lib / sinon / mock-expectation.js:78:14)
プロキシで(node_modules / sinon / lib / sinon / spy.js:89:22)
このコードが機能している間:
it('test withArgs stub', () => {
let fooStub = sinon.stub(C, 'foo');
fooStub.withArgs('a', 'b').returns(1);
fooStub.withArgs('c', 'd').returns(2);
expect(fooStub('a', 'b')).toEqual(1);
expect(fooStub('c', 'd')).toEqual(2);
fooStub.restore();
});
次のシナリオが期待どおりに機能することは言及する価値があります。
it('test one withArgs mock', () => {
let CMock = sinon.mock(C);
let fooStub = CMock.expects('foo');
fooStub.withArgs('a', 'b').returns(1);
expect(fooStub('a', 'b')).toEqual(1); // ok
CMock.restore();
});
it('test one withArgs mock', () => {
let CMock = sinon.mock(C);
let fooStub = CMock.expects('foo');
fooStub.withArgs('a', 'b').returns(1);
expect(fooStub('c', 'd')).toEqual(1); // error: foo received wrong arguments ["c", "d"], expected ["a", "b"]
CMock.restore();
});
つまり、この問題はwithArgs
複数回使用した場合にのみ発生します。
#1381に関連している可能性がありますが、例でわかるように、そこで提案された解決策は機能しません。
例示的な問題レポートをありがとう。 私はモック機能を使用していません。脳が痛くなるので、他の誰かがこれを見る必要がありますが、あなたの例はそれをはるかに簡単にするはずです。
自分でコードを自由に見てください-多くの場合、これを修正する最も簡単な方法です:-)
コードを見てみました。
まず第一に、このテストは機能します:
class C {
static foo(arg1, arg2) {return 'foo';}
}
it('test withArgs mock', () => {
let CMock = sinon.mock(C);
CMock.expects('foo').withArgs('a', 'b').returns(1);
CMock.expects('foo').withArgs('c', 'd').returns(2);
expect(C.foo('a', 'b')).toEqual(1);
expect(C.foo('c', 'd')).toEqual(2);
CMock.restore();
});
これが機能する理由と元の問題のテストが機能しない理由は2つあります。
expects
を作成します。expects
によって返されるメソッドの代わりに、静的メソッドを呼び出します。つまり、これも機能しません。
it('test withArgs mock', () => {
let CMock = sinon.mock(C);
CMock.expects('foo').withArgs('a', 'b').returns(1);
let fooStub = CMock.expects('foo').withArgs('c', 'd').returns(2);
expect(fooStub('a', 'b')).toEqual(1); // Error: foo received wrong arguments ["a", "b"], expected ["c", "d"]
expect(fooStub('c', 'd')).toEqual(2);
CMock.restore();
});
なぜそれが起こるのですか?
expects
が呼び出されるたびに、次のことが起こります。
minCalls/maxCalls
拡張されたスタブ- once()
を呼び出すと変更される変数)が作成されますが、それは「スコープ付きスタブ」であり、そうではありません。他のexpects
接続している。 expects
から返されたオブジェクトです。これにより、これらのシナリオで異なる動作が発生します。
expects
によって返されるメソッドを呼び出すと、そのexpects
のみに制限されます。expects
が検索され、適切なものが見つかります。 複数ある場合は、最初に呼び出されます。これは正しい動作ですか? 誰かがメソッドでexpects
を呼び出すと、それはstub
まったく同じように動作する(追加のminCalls/maxCalls
)というのがより直感的に思えます。 これにより、次のようになります。
stub
とmock-expectation
間でより多くのコードを共有できます。さて、 minCalls/maxCalls
どうなりますか?
現在expectation
は1つしかないため、モックを使用して呼び出し数の検証を行う3つの代替方法を提案します。
once()
、 twice()
などの連結を許可します。 let fooStub = CMock.expects('foo').withArgs('a', 'b').returns(1).twice();
fooStub.withArgs('c', 'd').returns(2).once(); // Does not affect the previous expectation.
ただし、少し混乱するかもしれません。
once()
、 twice()
などを連結しないでください。 CMock.expects('foo').withArgs('a', 'b').returns(1).twice(); // `twice()` returns `null`, so that one has to call `expects()` again to set expectations for other arguments.
CMock.expects('foo').withArgs('c', 'd').returns(2).once();
より明確ですが、 foo
複数回スタブすることはできないため、それを回避する方法が必要になります。 また、これはまだ可能です:
CMock.expects('foo').withArgs('a', 'b').returns(1).withArgs('c', 'd').returns(2).twice(); // I guess that this should only affect the last `withArgs`?
この問題は、最近のアクティビティがないため、自動的に古いものとしてマークされています。 それ以上のアクティビティが発生しない場合は閉じられます。 貢献していただきありがとうございます。
最も参考になるコメント
コードを見てみました。
まず第一に、このテストは機能します:
これが機能する理由と元の問題のテストが機能しない理由は2つあります。
expects
を作成します。expects
によって返されるメソッドの代わりに、静的メソッドを呼び出します。つまり、これも機能しません。
なぜそれが起こるのですか?
expects
が呼び出されるたびに、次のことが起こります。minCalls/maxCalls
拡張されたスタブ-once()
を呼び出すと変更される変数)が作成されますが、それは「スコープ付きスタブ」であり、そうではありません。他のexpects
接続している。expects
から返されたオブジェクトです。これにより、これらのシナリオで異なる動作が発生します。
expects
によって返されるメソッドを呼び出すと、そのexpects
のみに制限されます。expects
が検索され、適切なものが見つかります。 複数ある場合は、最初に呼び出されます。これは正しい動作ですか? 誰かがメソッドで
expects
を呼び出すと、それはstub
まったく同じように動作する(追加のminCalls/maxCalls
)というのがより直感的に思えます。 これにより、次のようになります。stub
とmock-expectation
間でより多くのコードを共有できます。さて、
minCalls/maxCalls
どうなりますか?現在
expectation
は1つしかないため、モックを使用して呼び出し数の検証を行う3つの代替方法を提案します。once()
、twice()
などの連結を許可します。ただし、少し混乱するかもしれません。
once()
、twice()
などを連結しないでください。より明確ですが、
foo
複数回スタブすることはできないため、それを回避する方法が必要になります。 また、これはまだ可能です: