Канал не получает локальные трансляции в тестовой среде - PullRequest
0 голосов
/ 03 апреля 2020

В настоящее время я пишу небольшую игру с Elixir и Phoenix, и у меня возникла проблема с написанием тестов для контроля производительности моей игры.

По сути, у меня есть GenServer, который зацикливается бесконечно, посылая Само бросает, который действует как основной l oop игры, обрабатывая большую часть логи c. Давайте назовем это "gamel oop". На каждой итерации gamel oop отправляет сообщение (через MyAppWeb.Endpoint.broadcast на канал, содержащий обновленное состояние игры. Канал получает это сообщение через handle_in и перенаправляет новое состояние игры всем подключенным клиентам. Канал также отправляет сообщение. сообщение, содержащее время, когда обновление состояния было получено на другой GenServer, который отслеживает различные метрики.

Это прекрасно работает в разработке и производстве, но не в тестах. Когда в тестовой среде канал не работает Кажется, я не получаю трансляции от gamel oop. Я могу подключиться к сокету, присоединиться к каналу и получить сообщения pu sh из него из тестового примера (спасибо ChannelCase), но что я делаю больше похож на интеграционный тест, поэтому отправка сообщений на канал из тестового примера не имеет смысла.

Это нормальное поведение? Если да, то есть ли способ изменить мою игру или архитектуру моего теста, которая будет работать лучше? Если нет, то какой шаг я пропускаю? Я смотрел в Интернете, но не мог найти ничего об этом. Я также пытался поиграть с конфигурацией тестовой среды (в частности, включив опцию server в конфигурации Endpoint), но не смог заставить ее работать.

Вот немного кода, чтобы лучше проиллюстрируйте, что я делаю.

Gamel oop GenServer:

defmodule MyApp.Gameloop do
  use GenServer
  alias MyAppWeb.Endpoint

  # Client

  def start_link([]) do
    GenServer.start(__MODULE__, [], name: __MODULE__)
  end

  # Server (callbacks)

  @impl true
  def init([]), do: {:ok, %{}}

  @impl true
  def handle_info(:loop, state) do
    updated_state = handle_game_logic(state)

    Endpoint.broadcast!("game_state", "new_state", updated_state)

    Process.send_after(self(), :loop, calculate_time_to_wait_based_on_tick_rate())

    {:noreply, updated_state}
  end
end

Сокет:

defmodule MyAppWeb.SpectateSocket do
  use Phoenix.Socket

  ## Channels
  channel "game_state", MyAppWeb.GameStateChannel

  def connect(_params, socket), do: {:ok, socket}

  def id(_socket), do: nil
end

Канал:

defmodule MyAppWeb.GameStateChannel do
  alias MyApp.Monitor
  alias :erlang, as: Erlang

  use MyAppWeb, :channel

  def join("game_state", _payload, socket) do
    {:ok, socket}
  end

  def handle_in("new_state", payload, socket) do
    broadcast(socket, "new_state", payload)
    Monitor.store_broadcast_time(Erlang.monotonic_time())
    {:noreply, socket}
  end
end

Опять же, это прекрасно работает в dev / prod, но handle_in канала никогда не вызывается в тестах.

Спасибо за любую помощь!

...