dashbitco / mox

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

Expect that a mocked function is never called #32

Closed jayashe closed 6 years ago

jayashe commented 6 years ago

Mox requires that, if a mock is used, we set an expectation for it. But expect requires that the number of invocations be greater than 0. Other mock libraries (like mockito) allow for verifying that a mocked method is never called. This would probably be useful for Mox.

Thoughts?

josevalim commented 6 years ago

@jgashe if you try to call something that has no expectation it will just raise today. And your test should fail accordingly.

jayashe commented 6 years ago

I'd like to have a test pass if something is never called. The function never being called is my expected behavior.

Imagine code like this:

def conditional_call(my_condition) do
  if (my_condition) do
    MyMock.call()
  else
    do_nothing
  end
end

If I want to test both branches of this, I'd call conditional_call with both true and false. If I'm writing a test for calling conditional_call with false, I'd want to expect that MyMock.call is never called, and have the test fail if MyMock.call is called.

Mox doesn't let me do this because it raises if the Mock doesn't have any expectation, and doesn't have a pattern match of expect where n = 0.

josevalim commented 6 years ago

Mox doesn't let me do this because it raises if the Mock doesn't have any expectation

What do you mean? If you don't set any expectation that is fine by Mox.

jayashe commented 6 years ago

Oh yeah you're totally right.

Closed.

NikitaAvvakumov commented 6 years ago

@josevalim If the call to a function with no expectations takes place asynchronously, though, the Mox.UnexpectedCallError is logged but does not lead to test failure. Is there a way around this?

josevalim commented 6 years ago

@NikitaAvvakumov if the process is not linked to the test process in any way, then the failures won't cascade, and your test won't fail. this is a general property of Elixir, not necessarily related to mox.

NikitaAvvakumov commented 6 years ago

@josevalim But in this particular case, could test failures be enforced by adding to Mox either expect(m, f, 0, _fn) or a new function like refute or expect_not, like the OP was asking? If such existed, it could be combined with allowances or global mode and verify!/verify_on_exit! to cause tests to fail and, arguably, make their intentions more explicit.

josevalim commented 6 years ago

@NikitaAvvakumov oh, I see what you mean. That sounds good to me. Can you please send a PR?

NikitaAvvakumov commented 6 years ago

@josevalim I'll gladly give it a shot. Which option sounds better to you - expect accepting n = 0 or refute or similarly named new function?

josevalim commented 6 years ago

expect with 0.

steffkes commented 6 years ago

@josevalim just reading through older issues. this seems to be addressed in #35 which is already merged, right?

josevalim commented 6 years ago

correct! thanks!