dashbitco / mox

Mocks and explicit contracts in Elixir
1.35k stars 77 forks source link

Make behaviour of `stub` equal to `expect` #28

Closed opsb closed 6 years ago

opsb commented 6 years ago

My initial impression was that the only difference between stub and expect was that expect calls would be verified whereas stub calls would not. Looking closer though I found

expect/4 can also be invoked multiple times for the same name/arity, allowing you to give different behaviours on each invocation.

stub/3 will overwrite any previous calls to stub/3.

I have a test where I need to stub different returns depending on the invocation (i.e. first or second). I don't want to verify this behaviour because the return is used to generate side effects which are verified later on. Currently I need to expect the calls because it's the only way of returning different responses.

Is there any reason not to align stub and expect so that they're identical except for the verification step?

josevalim commented 6 years ago

The stub is a function, in there you can do anything, including return different types based on the argument. The reason we don't allow you to declare multiple stubs is because expects can be conflicting. They will always be invoked in order. Although conflicting stubs means one of them will never be invoked, hence it is better to handle them in a single code snippet.

opsb commented 6 years ago

@josevalim the particular scenario that I'm looking at requires different return values for the same arguments depending in which invocation it is.

The reason we don't allow you to declare multiple stubs is because expects can be conflicting. They will always be invoked in order. Although conflicting stubs means one of them will never be invoked, hence it is better to handle them in a single code snippet.

This is the point I was trying to make, that all expects are invoked but with stub the conflicts will be dropped. Is there any reason for them to be different in this respect?

josevalim commented 6 years ago

The reason is literally the part you quoted. If you expect different values for the same arguments, how would we know which stub to invoke since every stub can be invoked infinite times?

opsb commented 6 years ago

Put another my question is, would it be unreasonable for stub to behave the same way as expect but without the validation step. It sounds like it's desirable to allow stubs to be invoked infinite times though in which case it would need to be a different call (possibly expect(validate: false) or something entirely). expect certainly allows me to get green tests, but my initial impression was that stub was used to simply indicate that an invocation was optional rather than verified. I suppose you could make the argument that once you introduce ordering that the individual invocations should be verified anyway.