1

Is it possible to mock a sequence of return values with ExUnit Mock the same way meck provides this functionality in Erlang?

...
meck:new(my_module),
meck:sequence(my_module, method, 1, [Response1, Response2]),
meck:unload(module),
...

If not, is it possible to successfully combine meck and mock in the same unit test ExUnit Elixir module?

David
  • 595
  • 1
  • 8
  • 19

2 Answers2

2

There's no mention of :meck.sequence in mock.ex so I'm guessing this is not supported yet.

It should be fine to call :meck functions directly as long as it's outside a Mock.with_mock call and you make sure to call :meck.unload/1 after you're done. (And you use async: false, as Mock already requires.) This should be fine even in the same test.

test "the truth" do
  url = "http://www.google.com"

  :meck.new(HTTPoison)
  :meck.sequence(HTTPoison, :get!, 1, [%{body: "foo"}, %{body: "bar"}])
  assert HTTPoison.get!(url).body == "foo"
  assert HTTPoison.get!(url).body == "bar"
  assert HTTPoison.get!(url).body == "bar"
  :meck.unload(HTTPoison)

  assert HTTPoison.get!(url).body =~ "HTML"

  with_mock HTTPoison, [get!: fn(_url) -> %{body: "baz"} end] do
    assert HTTPoison.get!(url).body == "baz"
  end

  assert HTTPoison.get!(url).body =~ "HTML"
end

Demo:

$ mix test
.

Finished in 0.2 seconds
1 test, 0 failures
Dogbert
  • 212,659
  • 41
  • 396
  • 397
0

The Mock library has in_series/2 helper which allows to mock sequence of calls.

Here is excerpt from the docs and related PR adding this featre.

defmodule MyTest do
  use ExUnit.Case, async: false

  import Mock

  test "mock repeated calls with in_series" do
    with_mock String,
      [slice: [in_series(["test", 1..3], ["string1", "string2", "string3"])]]
    do
      assert String.slice("test", 1..3) == "string1"
      assert String.slice("test", 1..3) == "string2"
      assert String.slice("test", 1..3) == "string3"
    end
  end
end

the other way to achieve the same result would be

with_mock(Ecto.UUID, generate: [
  {[], :meck.seq(["uuid-1", "uuid-2"])}
]) do
  Ecto.UUID.generate() # => "uuid-1"
end
achempion
  • 794
  • 6
  • 17