正确测试GenServer和Supervisor

时间:2018-11-03 20:26:15

标签: elixir

对于在Elixir中实现Genserver来说,我还很陌生。我有一种情况,我正在尝试管理某些状态,Genserver在这种情况下工作得很好。但是,在测试Genserver时,我遇到了一些麻烦。

我有两个测试似乎相互碰撞。我对我的Genserver进行了单元级测试,对更高级别的测试进行了调用,该函数调用的功能是将Genserver与模块一起使用。这是我的两个测试用例:

第一:

defmodule MyApp.ScoreTableQueueTest do
  use MyApp.DataCase

  alias MyApp.{ScoreTableQueue}

  setup do
    start_supervised(ScoreTableQueue)
    :ok
  end

  test "pushes value in the queue" do
    assert :ok == ScoreTableQueue.push([1,2,3,4])
  end

  test "pops the full value of the queue" do
    assert [[1,2,3,4]] == ScoreTableQueue.pop()
  end
end

如果我单独运行此命令,则每次都会通过。但是,如果我运行此测试,它将定期中断:

第二:

  setup do
    start_supervised(ScoreTableQueue)
    :ok
  end

  describe "distribute" do
    test "it distrbutes the correct season points" do
      {:ok, table} = List.first(MyApp.ScoreTableAllocator.distribute())

      assert table.table_details.information == [
               %{team_id: team_3.id, team_score: "N/A"},
               %{team_id: team_2.id, team_score: ps_2.score},
               %{team_id: team_1.id, team_score: ps_1.score}
             ]

      assert table.question_id == question.id
      assert table.season_id == season.id
    end
  end

实际上,在我的distribute/1函数中使用了Genserver。如果我单独调用此测试,则每次都能正常运行。但是,当我一起运行测试时,似乎花了一半的时间,使我相信我正在启动同一台服务器,并在两次测试之间将信息传递到同一台服务器。

我的问题:如何将每个测试彼此分开?我希望每种测试的每种情况(至少每个文件)都具有完全不同的服务器。 Elixir的方法是什么?

1 个答案:

答案 0 :(得分:1)

在这种情况下,我建议修改模块的API函数以接受要使用的服务器,默认情况下使用全局实例。遵循以下原则:

defmodule MyApp.ScoreTableQueue do
  use GenServer

  def push(server \\ __MODULE__, item) do
    GenServer.call(server, {:push, item})
  end

  ...
end

然后在测试中,您只需为每个测试启动一个实例:

setup do
  {:ok, pid} = GenServer.start_link(MyApp.ScoreTableQueue, _init_args = nil)
  {:ok, queue: pid}
end

test "pushes value in the queue", %{queue: queue} do
  assert :ok == ScoreTableQueue.push(queue, [1,2,3,4])
end

当您开始使用start_supervised时,它是根据模块中的child_spec函数启动的-我假设它指定了服务器的全局实例,因此这两个测试很可能会干扰每个其他。

另一个选择是将测试设置为同步(通过使用use MyApp.DataCase, async: false),以使它们永远不会同时运行。这可能甚至更简单,但是如果测试套件很大,则速度可能会变慢。