首页 > 解决方案 > ExUnit - 如何通过命名设置函数将上下文传递给描述块中的测试宏

问题描述

查看 ExUnit 文档,您可以context使用以下模式向结构添加属性:

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

但是在使用describe宏块时,我们鼓励您使用以下形式为您的测试提供设置函数:

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

效果很好,但是没有提到在使用describe宏和命名设置时如何将新属性添加到上下文结构以在测试中使用。

到目前为止,我已经尝试过(快速总结):

  ...
  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
  ...

以这种方式为描述块创建设置函数时,实际上是否可以操纵测试套件上下文?

标签: elixirelixir-mixex-unit

解决方案


您正在正确地进行设置部分。命名的设置函数将上下文作为参数,它们的返回值会自动合并到上下文中。因此,您实际上已经拥有:test可用于测试的密钥。

您只需要在测试中获取上下文作为第二个参数,如下所示:

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

但是,更有趣的是,您可以使用模式匹配从上下文中获取您想要的确切键:

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

推荐阅读