GenServer and Supervisors - how to test them?

Hi,
I have a module GameSupervisor - dynamic supervisor thats starts as a child of my app and a module GameServer with function new_game - which calls GameSupervisor.start_child:

GameServer 
 def new_game(game_id, player_id) do
    GameSupervisor.start_child(game_id, player_id)
  end

 def start_link(game_id: game_id, player_id: player_id) do
    GenServer.start_link(__MODULE__, player_id, name: via_tuple(game_id))
  end

GameSupervisor
def start_child(game_id, player_id) do
    spec = {Ships.Server.GameServer, game_id: game_id, player_id: player_id}
    DynamicSupervisor.start_child(__MODULE__, spec)
  end

 def start_link(_init_arg) do
    DynamicSupervisor.start_link(__MODULE__, [], name: __MODULE__)
  end

I’m not sure how to test my GameServer, because in each test I call the new_game function and in each test I have to use a different game_id, because using the same id over and over again I can’t start new games, because processes with the same id remain active from other tests.
Therefore, what should the correct testing look like in such a situation?
Should I use a different game_id in each test or would it be best to change the function start_child and in tests start GameSupervisor using start_supervised?

GameSupervisor.start_child(supervisor_name, game_id, player_id)

Another question that I have is what is the right way to test GenServers whose functions only refer to other modules that have already been tested.

GameServer
  def join_game(game_id, player_id) do
    GenServer.call(via_tuple(game_id), {:join_game, player_id})
  end

def handle_call({:join_game, player_id}, _from, state) do
    {response, state} = Game.join_game(state, player_id)

    {:reply, response, state}
  end

If I’ve already tested Game.join_game then I’m not sure what I can test without duplicating tests from the Game module.

Hi, @lucas0dev :wave: and welcome!

Should I use a different game_id in each test or would it be best to change the function start_child and in tests start GameSupervisor using start_supervised?

Using start_supervised would be the first thing I thought of. Make your GameSupervisor accept a :name so that you can configure it for tests and probably default it to __MODULE__ as you currently do for the actual application.

And it wouldn’t bother to also add a test that would test the default one, kinda to make sure that despite being tested in isolation it’s actually there and running :slightly_smiling_face: