Last Wednesday I went to Elixir Meetup in Cracow’s headquarters of Erlang Solutions. It was supposed to be about basics of Elixir and how pipe operator influenced the software design, but I learned another priceless lesson. I’ve been testing GenServers callbacks wrong whole time…

I was usally doing it by spawning a process in setup the same way I would do in the supervision tree. Don’t get me wrong it’s totally cool for integration tests.

  setup do
    {:ok, instance } = RandomModule.start_link
    {:ok, thing: instance}

  test "spawns buckets", %{thing: process} do
    assert Module.do_stuff(process, args) == something
    #Do any other black test magick

The only thing we’re doing here is testing input and output of callback basically. What if we could just test the callback itself? But wait… We can!

Let’s assume we have Stuff module defined like so.

defmodule Stuff do

defmodule State do
  defstruct data: [], name: "Garry"

def handle_call({:do, stuff}, _caller, state) do
  thing = complicated_and_fun_computations(stuff,
  {:reply, thing, %State{state | data: [thing |]}}

We can test it just by calling handle_call with proper arguments or at least arguments that program would expect…

test "computations compute expected result" do
  {:reply, result, _whatever } = Stuff.handle_call({:do, "fun data"}, self, %Stuff.State{})
  assert result = something