Que vous attendiez-vous à ce qu'il se passe?
Lorsque je crée une simulation sur une classe et que j'essaie de contrôler le comportement de l'une de ses fonctions à l'aide de withArgs
, une exception est levée. Se produit uniquement lors de l'utilisation de plusieurs appels de withArgs
.
Que se passe-t-il réellement
Comment reproduireExemple reproductible
Supposons que j'ai déclaré une classe C
:
class C {
static foo(arg1, arg2) {return 'foo';}
}
J'essaie de contrôler le comportement de foo
utilisant un simulacre sur C
:
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();
});
Ce qui lève l'exception suivante :
ExpectationError : foo a reçu des arguments erronés ["a", "b"], attendu ["c", "d"]
à Object.fail (node_modules/sinon/lib/sinon/mock-expectation.js:281:25)
à Fonction.(node_modules/sinon/lib/sinon/mock-expectation.js:182:33)
à Array.forEach (natif)
à Function.verifyCallAllowed (node_modules/sinon/lib/sinon/mock-expectation.js:175:27)
à Function.invoke (node_modules/sinon/lib/sinon/mock-expectation.js:78:14)
au proxy (node_modules/sinon/lib/sinon/spy.js:89:22)
Pendant que ce code fonctionne :
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();
});
Il convient de mentionner que les scénarios suivants fonctionnent comme prévu :
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();
});
Cela signifie que le problème se produit uniquement lors de l'utilisation de withArgs
plusieurs fois.
Cela peut être lié à #1381, mais comme vous pouvez le voir dans l'exemple, la solution suggérée ne fonctionne pas.
Merci pour un exemple de rapport de problème. Je n'utilise pas la fonctionnalité de simulation, car cela me fait mal au cerveau, donc quelqu'un d'autre devra y jeter un œil, mais vos exemples devraient rendre cela beaucoup plus facile.
N'hésitez pas à jeter un œil au code vous-même - souvent le moyen le plus rapide de résoudre ce problème :-)
J'ai regardé le code.
Tout d'abord, ce test fonctionne :
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();
});
Il y a deux raisons pour lesquelles cela fonctionne et le test du numéro d'origine ne fonctionne pas :
expects
.expects
.Cela signifie que cela ne fonctionne pas non plus :
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();
});
Pourquoi cela arrive-t-il ?
Chaque fois que expects
est appelé, ce qui suit se produit :
minCalls/maxCalls
- qui sont les variables qui sont modifiées lorsque vous appelez once()
par exemple) est créée, seulement qu'il s'agit d'un "stub étendu", il avoir une connexion avec d'autres expects
. C'est l'objet renvoyé par expects
.Ce qui se traduit par des comportements différents pour ces scénarios :
expects
, elle sera limitée uniquement à ce expects
.expects
et en trouvera un qui convient. S'il y en a plusieurs, il appellera le premier.Est-ce le comportement correct ? Il me semble plus intuitif qu'une fois que quelqu'un appelle expects
sur une méthode, elle se comportera exactement comme un stub
(avec le minCalls/maxCalls
supplémentaire). Cela se traduira par :
stub
et mock-expectation
.Maintenant, qu'arriverait-il à minCalls/maxCalls
?
Puisqu'il n'y a qu'un seul expectation
maintenant, je propose trois façons alternatives de vérifier le nombre d'appels avec des simulations :
once()
, twice()
etc. let fooStub = CMock.expects('foo').withArgs('a', 'b').returns(1).twice();
fooStub.withArgs('c', 'd').returns(2).once(); // Does not affect the previous expectation.
Peut-être un peu déroutant cependant.
once()
, twice()
etc. 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();
Plus clair, mais vous ne pouvez pas stub foo
plus d'une fois, nous aurons donc besoin d'un moyen de contourner cela. De plus, cela reste possible :
CMock.expects('foo').withArgs('a', 'b').returns(1).withArgs('c', 'd').returns(2).twice(); // I guess that this should only affect the last `withArgs`?
Ce problème a été automatiquement marqué comme obsolète car il n'a pas eu d'activité récente. Il sera fermé si aucune autre activité ne se produit. Merci pour vos contributions.
Commentaire le plus utile
J'ai regardé le code.
Tout d'abord, ce test fonctionne :
Il y a deux raisons pour lesquelles cela fonctionne et le test du numéro d'origine ne fonctionne pas :
expects
.expects
.Cela signifie que cela ne fonctionne pas non plus :
Pourquoi cela arrive-t-il ?
Chaque fois que
expects
est appelé, ce qui suit se produit :minCalls/maxCalls
- qui sont les variables qui sont modifiées lorsque vous appelezonce()
par exemple) est créée, seulement qu'il s'agit d'un "stub étendu", il avoir une connexion avec d'autresexpects
. C'est l'objet renvoyé parexpects
.Ce qui se traduit par des comportements différents pour ces scénarios :
expects
, elle sera limitée uniquement à ceexpects
.expects
et en trouvera un qui convient. S'il y en a plusieurs, il appellera le premier.Est-ce le comportement correct ? Il me semble plus intuitif qu'une fois que quelqu'un appelle
expects
sur une méthode, elle se comportera exactement comme unstub
(avec leminCalls/maxCalls
supplémentaire). Cela se traduira par :stub
etmock-expectation
.Maintenant, qu'arriverait-il à
minCalls/maxCalls
?Puisqu'il n'y a qu'un seul
expectation
maintenant, je propose trois façons alternatives de vérifier le nombre d'appels avec des simulations :once()
,twice()
etc.Peut-être un peu déroutant cependant.
once()
,twice()
etc.Plus clair, mais vous ne pouvez pas stub
foo
plus d'une fois, nous aurons donc besoin d'un moyen de contourner cela. De plus, cela reste possible :