mardi 22 septembre 2015

How to record/verify method calls in unit tests without mocks?

How can I write expectations in my unit tests ?

Here is an example:

defmodule MyAPIModule do
  @url "http://example.com/path"

  def get_something(http_module \\ HTTPoison) do
    http_module.get!(@url, [], [])
  end
end

Here is my test:

defmodule MyAPIModuleTest do
  use ExUnit.Case

  test "Runs the get! method with no headers and no params" do
    MyAPIModule.get_something(HttpSpy)
    # 1) assert that get! was called
    # 2) assert [] == headers
    # 3) assert [] == params
    # 4) assert "http://example.com/path" == url
  end
end

defmodule HttpSpy do
  def get!(url, headers, params) do
    #
  end
end

My problem is immutability. I can't simply create a list in the HttpSpy module and record method calls with their params into that list.

So I tried to change HttpSpy this way:

defmodule HttpSpy do
  def start(listener) do
    spawn_link(__MODULE__, loop, [listener])
  end

  def loop(listener) do
    receive do

    end
  end

  def get!(url, headers, params) do

  end
end

and I changed the test to:

test "Runs the get! method with no headers and no params"
  spy = HttpSpy.start(self)
  MyAPIModule.get_something(HttpSpy)
  receive do
    {^spy, method_call} -> flunk("wrong method call")
    after 1000 -> flunk("timeout")
  end
end

but I'm stuck. HttpSpy.get! does not know the PID of the HttpSpy process spawned by the test. Therefore HttpSpy.get! cannot send a message to the process which is waiting in the loop method. Therefore the loop method will never send to the test (which I call listener) the function called and its params.

I realize that what I want is basically mock and expectations but I'd like to find the idiomatic way (= no mocks) to do it.

Aucun commentaire:

Enregistrer un commentaire