Charlie
Charlie

Reputation: 4329

ExUnit - How to pass context to test macros in describe blocks, via named setup functions

Looking at the ExUnit documentation, you can add properties to the context struct with the following pattern:

defmodule KVTest do
  use ExUnit.Case

  setup do
    {:ok, pid} = KV.start_link
    {:ok, pid: pid}
    # "[pid: pid]" also appears to work...
  end

  test "stores key-value pairs", context do
    assert KV.put(context[:pid], :hello, :world) == :ok
    assert KV.get(context[:pid], :hello) == :world

    # "context.pid" also appears to work...
  end
end

But when using describe macro blocks, you're encouraged to use the following form to provide setup functions for your tests:

defmodule UserManagementTest do
  use ExUnit.Case, async: true

  describe "when user is logged in and is an admin" do
    setup [:log_user_in, :set_type_to_admin]

    test ...
  end

  describe "when user is logged in and is a manager" do
    setup [:log_user_in, :set_type_to_manager]

    test ...
  end

  defp log_user_in(context) do
    # ...
  end
end

Which works well, but there's no mention of how to add new properties to the context struct to use in tests, when using the describe macro and named setups.

So far, I've tried (quick summary):

  ...
  describe "when user is logged in and is a manager" do
    setup [:test]

    test(context) do
       IO.puts("#{ inspect context }") # Comes up as 'nil'
    end
  end

  defp test(context) do
    [test: "HALLO"]
  end
  ...

Is it actually possible to manipulate the test suite context when creating setup functions for describe blocks in this way?

Upvotes: 2

Views: 2215

Answers (1)

Marcelo De Polli
Marcelo De Polli

Reputation: 29281

You're doing the setup part correctly. The named setup functions take the context as a parameter and their return is automatically merged into the context. So you actually already have the :test key available for your tests.

You just need to grab the context in your tests as a second argument, like this:

describe "when user is logged in and is a manager" do
  setup [:test]

  test "does the right thing", context do
     IO.inspect(context) # Will not come up as nil
  end
end

But, more interestingly, you can use pattern matching to grab the exact keys you want from the context:

describe "when user is logged in and is a manager" do
  setup [:test]

  test "does the right thing", %{test: test} do
     IO.inspect(test) # "HALLO"
  end
end

Upvotes: 3

Related Questions