How to stub (or prevent running) of a call to a worker in my ExUnit test?

2.1k views Asked by At

I have a Phoenix app (which is just a restful api with no front end) and one of the controllers does some stuff which I want to test, but at the end of the controller it calls a dispatcher which sends a payload off to a worker (run under poolboy) to process the received payload in the background.

In my controller test, I don't actually want to test the stuff the worker is doing, I just want to know that the dispatcher for the worker has been called with the correct payload (e.g. calledWith() )

And ideally the dispatcher function to be stubbed, so the actual thing is never ran.

I could pass an additional parameter to the dispatcher to ensure it never runs the code on the worker, but that seems very messy, whereas a stub seems idea.

Thanks

Edit

Dispatcher code:

defmodule Convert.Dispatcher do
  def dispatch(data) fo
   spawn (fn() -> parallel(data) end)
  end

  def parallel(data) do
    #pass off to poolboy
  end
end

Test mock:

with_mock Convert.Dispatcher, [dispatch: fn(_opts) -> :ok end] do
  response = conn(:post, "/", data) |> send_request
  body = response.resp_body |> Poison.decode!
  assert response.status == 201
  assert called Convert.Dispatcher.dispatch("")
end
1

There are 1 answers

12
Patrick Oscity On BEST ANSWER

There is a mocking library called "mock" that you can use to temporarily mock modules in your tests. For example:

defmodule MyControllerTest do
  use ExUnit.Case, async: false
  use RouterHelper
  import Mock

  setup do
    Logger.disable(self())
    :ok
  end

  test "dispatches a worker" do
    with_mock MyDispatcher, [dispatch: fn(_opts) -> :ok end] do
      call(Router, :get, "/my/route")
      assert called MyDispatcher.dispatch(foo: "bar")
    end
  end
end