Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Testing GenServers

testing_genservers.livemd

Testing GenServers

Section

[head | tail] = []
[] ++ ["hello"]
opts = [initial_state: ["one", "two"], name: :example]
{value, opts} = Keyword.pop(opts, :name, :my_module)
defmodule TodoList do
  use GenServer

  def start_link(opts) do
    name = Keyword.pop(opts, :name, __MODULE__) |> IO.inspect()
    GenServer.start_link(__MODULE__, opts, name: __MODULE__)
  end

  def add(pid, todo_item) do
    GenServer.call(pid, {:add_item, todo_item})
  end

  def complete_next(pid) do
    GenServer.call(pid, :complete_item)
  end

  def init(opts) do
    {:ok, opts}
  end

  def handle_call({:add_item, todo_item}, _from, state) do
    next_state = state ++ [todo_item]
    {:reply, :ok, next_state}
  end

  def handle_call(:complete_item, _from, []) do
    {:reply, nil, []}
  end

  def handle_call(:complete_item, _from, state) do
    [head | tail] = state
    {:reply, head, tail}
  end
end
TodoList.start_link([])
ExUnit.start(auto_run: false)

defmodule GenServerTest1 do
  use ExUnit.Case, async: true

  test "start_link/1" do
    assert {:ok, pid} = TodoList.start_link([])
  end

  test "add/2" do
    assert {:ok, pid} = TodoList.start_link([])
    assert :ok = TodoList.add(pid, "one")
    assert :ok = TodoList.add(pid, "two")
    assert TodoList.complete_next(pid) == "one"
    assert TodoList.complete_next(pid) == "two"
  end
end

defmodule GenServerTest2 do
  use ExUnit.Case, async: true

  test "start_link/1" do
    assert {:ok, pid} = TodoList.start_link([])
  end

  test "add/2" do
    assert {:ok, pid} = TodoList.start_link([])
    assert :ok = TodoList.add(pid, "one")
    assert :ok = TodoList.add(pid, "two")
    assert TodoList.complete_next(pid) == "one"
    assert TodoList.complete_next(pid) == "two"
  end

  test "complete_next/1" do
    assert {:ok, pid} = TodoList.start_link(["one", "two"])
    assert TodoList.complete_next(pid) == "one"
    assert TodoList.complete_next(pid) == "two"
    assert TodoList.complete_next(pid) == nil
  end

  # test "handle_cast :add implementation" do
  #   assert {:ok, pid} = GenServer.start_link(TodoList, [])
  #   assert :ok = GenServer.cast(pid, {:add, "one"})
  #   assert :ok = GenServer.cast(pid, {:add, "two"})
  #   assert :sys.get_state(pid) == ["one", "two"]
  # end

  # test "handle_call :complete implementation" do
  #   assert {:ok, pid} = GenServer.start_link(TodoList, [])
  #   assert :ok = GenServer.cast(pid, {:add, "one"})
  #   assert :ok = GenServer.cast(pid, {:add, "two"})

  #   assert :sys.get_state(pid) == ["one", "two"]
  #   assert GenServer.call(pid, :complete) == "one"

  #   assert :sys.get_state(pid) == ["two"]
  #   assert GenServer.call(pid, :complete) == "two"

  #   assert :sys.get_state(pid) == []
  #   assert GenServer.call(pid, :complete) == nil
  # end
end

ExUnit.run()
state = []
[head | tail] = state
defmodule TodoList do
  use GenServer

  def start_link(opts) do
    name = Keyword.get(opts, :name, __MODULE__)
    GenServer.start_link(__MODULE__, [], name: name)
  end

  def add(pid, todo_item) do
    GenServer.call(pid, {:add_item, todo_item})
  end

  def complete_next(pid) do
    GenServer.call(pid, :complete_item)
  end

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

  @impl true
  def handle_call({:add_item, todo_item}, _from, state) do
    {:reply, :ok, state ++ [todo_item]}
  end

  @impl true
  def handle_call(:complete_item, _from, []) do
    {:reply, nil, []}
  end

  @impl true
  def handle_call(:complete_item, _from, state) do
    [head | tail] = state
    {:reply, head, tail}
  end
end
pid = Process.whereis(:example_name)

unless Process.alive?(pid) do
  TodoList.start_link(name: :example_name)
end
ExUnit.start(auto_run: false)

defmodule TodoListTest do
  use ExUnit.Case

  # Robust
  # Client API
  test "Behavior Test" do
    assert {:ok, pid} = TodoList.start_link(name: :behavior)

    assert TodoList.add(pid, "one") == :ok
    assert TodoList.add(pid, "two") == :ok

    assert TodoList.complete_next(pid) == "one"
    assert TodoList.complete_next(pid) == "two"
    assert TodoList.complete_next(pid) == nil
  end

  # Brittle
  # Server Callbacks
  test "Implementation Test" do
    assert {:ok, pid} = GenServer.start_link(TodoList, name: :implementation)

    assert :ok = GenServer.call(pid, {:add_item, "one"})
    assert :ok = GenServer.call(pid, {:add_item, "two"})

    assert :sys.get_state(pid) == ["one", "two"]

    assert GenServer.call(pid, :complete_item) == "one"
    assert :sys.get_state(pid) == ["two"]

    assert GenServer.call(pid, :complete_item) == "two"
    assert :sys.get_state(pid) == []

    assert GenServer.call(pid, :complete_item) == nil
    assert :sys.get_state(pid) == []
  end
end

ExUnit.run()