Hello. I have a GenServer working correctly. All the test are passing.
This is how I have it defined:
defmodule CashierGenServer do
def start_link(arg, opts \\ []) do
name = Keyword.get(opts, :name, __MODULE__)
GenServer.start_link(__MODULE__, arg, name: name)
end
@spec add_to_cart(product_code :: String.t()) :: :ok
def add_to_cart(product_code) do
GenServer.cast(__MODULE__, {:add_to_cart, product_code})
end
... # a lot more client code, that resembles this
def init(_) do
state = %{total_price_expected: 0, basket: [], inventory: []}
{:ok, state, {:continue, :fetch_inventory_from_fake_database}}
end
def handle_continue(:fetch_inventory_from_fake_database, state) do
{:noreply, %{state | inventory: Inventory.retrieve_inventory()}}
end
... # a lot more server code but more of the same
end
My tests are defined like this:
defmodule CashierGenServerTest do
use ExUnit.Case, async: true
doctest CashierGenServer
import CashierGenServer
setup do
start_supervised(CashierGenServer)
:ok
end
test "application starts with an empty cart and zero initial amount" do
assert consult_cashier_info()[:basket] == []
assert consult_cashier_info()[:total_price_expected] == 0
end
test "application starts loading the products inventory" do
assert consult_cashier_info()[:inventory] == Inventory.retrieve_inventory()
end
test "add_to_cart/1 allows adding products to the cart" do
product = Fixtures.product_fixture(["GR1"])
assert consult_cashier_info()[:basket] == product
end
test "remove_from_cart/1 removes one unit of a product from the cart" do
[product] = Fixtures.product_fixture(["GR1"])
remove_from_cart(product)
assert consult_cashier_info()[:basket] == []
end
... # more tests
end
AGAIN, ALL OF THESE TESTS ARE PASSING WITH NO ISSUES
But if I supervise this GenServer my tests wonāt pass. Some will pass, some will not. Itās like the previous state remains in the test.
This is how I supervised it.
defmodule CashierGenServer.Application do
@moduledoc false
use Application
@impl true
def start(_type, _args) do
children = [
CashierGenServer
]
opts = [strategy: :one_for_one, name: CashierGenServer.Supervisor]
Supervisor.start_link(children, opts)
end
end
I noticed that if I do this on my test setup
setup do
Application.stop(:cashier_gen_server)
:ok = Application.start(:cashier_gen_server)
end
my tests will pass.
-
Is this the correct way?
-
If not, what do you recommend me to properly test a supervised GenServer?