【问题标题】:elixir test fails with "Reason: already started"长生不老药测试失败,“原因:已经开始”
【发布时间】:2020-12-27 04:15:46
【问题描述】:

我目前正在处理我的第一个大型 Elixir 项目,并且希望这次能够适当地利用测试。 但是,如果我将我的模块添加到“普通”主管,我无法使用start_supervised! 再次启动它们,并且所有测试都以Reason: already started: #PID<0.144.0> 失败

这是我的代码:

(应用程序.ex)

    defmodule Websocks.Application do
  # See https://hexdocs.pm/elixir/Application.html
  # for more information on OTP Applications
  @moduledoc false

  use Application

  def start(_type, _args) do
    children = [
      {Websocks.PoolSupervisor, []},
      {Websocks.PoolHandler, %{}}
      # {Websocks.Worker, arg}
    ]

    # See https://hexdocs.pm/elixir/Supervisor.html
    # for other strategies and supported options
    opts = [strategy: :one_for_one, name: Websocks.Supervisor]
    Supervisor.start_link(children, opts)
  end
end

我的一些测试:

defmodule PoolHandlerTest do
  use ExUnit.Case, async: true
  alias Websocks.PoolHandler
  doctest PoolHandler

  setup do
    start_supervised!({PoolHandler, %{}})
    %{}
  end

  test "adding two pools and checking if they are there" do
    assert PoolHandler.add(:first) == :ok
    assert PoolHandler.add(:second) == :ok
    assert PoolHandler.get_pools() == {:ok,%{:first => nil, :second => nil}}
  end

和池处理程序:

defmodule Websocks.PoolHandler do
  use GenServer

  # Client
  def start_link(default) when is_map(default) do
    GenServer.start_link(__MODULE__, default, name: __MODULE__)
  end

  # Server (callbacks)

  @impl true
  def init(arg) do
    {:ok, arg}
  end
end

(我认为不需要的东西我删掉了,但完整的代码在github上:github

提前感谢我得到的任何帮助!

【问题讨论】:

  • 我认为您不需要为application.ex 中列出的测试开始工作——据我所知,application.ex 中的所有内容都是在您进行测试运行时开始的。

标签: testing elixir


【解决方案1】:

正如@Everett 在评论中提到的-当您mix test 时,您的应用程序已经为您启动,因此无需再次启动您的GenServers。看起来您正在与测试中的全局实例进行交互,所以如果这是您想要的,那么它应该可以工作。

但是,如果您想为您的测试启动一个单独的实例,您需要启动一个未命名的实例。例如,您可以在包装函数中添加一个可选的 pid 参数:

defmodule Websocks.PoolHandler do

  # ...

  def add(server \\ __MODULE__, value) do
    GenServer.call(server, {:add, value})
  end

  # ...

end

然后,您可以在 setup 中启动一个未命名的实例,然后在测试中使用它,而不是像您一样使用 start_supervised!

setup do
  {:ok, pid} = GenServer.start_link(PoolHandler, %{})
  {:ok, %{handler: pid}}
end

test "adding two pools and checking if they are there", %{handler: handler} do
  PoolHandler.add(handler, :first)
  # ...
end

【讨论】:

  • “你需要创建一个未命名的”——从技术上讲,它可能已命名,只是名称必须与已注册的名称不同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-09-29
  • 1970-01-01
  • 2016-02-01
  • 1970-01-01
  • 2010-09-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多