ETS gets stopped inside on_exit callback in Tests

I am trying to start a few named GenServers and then try to stop them. Before terminating the terminate/2 is called where the state of GenServer gets stored in :ets relation.

describe "sites" do
    setup do

      # some sites that will be used for naming GenServer
      sites = [:s1, :s2, :s3, :s4]
      
      # starting a new GenServer with site names. this will also create an :ets table for storing cache
       Sites.new(sites)

      IO.inspect(:ets.whereis(:s1_cache), label: :setup)
      #Reference<0.3131894567.490864646.163685>

      Enum.each(sites, fn site ->
        on_exit(fn ->
          IO.inspect(:ets.whereis(:s1_cache), label: :on_exit)
          # :undefined ?

         Sites.stop(site)
        end)
      end)

      {:ok, sites: sites}
    end

    test "checking state of a site", %{sites: [:s1, _, _, _]} do
      IO.inspect(:ets.whereis(:s1_cache), label: :test)
      #Reference<0.3131894567.490864646.163685>
      
     assert :s1 = Sites.state(:s1).site_name
    end
end

Is there any way that I can access the :ets table when calling on_exit callback ??

How do you start Sites? If you start it linked, then the process might already be stopped at the time on_exit callbacks are executed. The setup code runs in the test process, just like the body of the test. But once the test is done the test process exits. on_exit callbacks run in a separate process.

When i don’t use on_exit then individual tests run completely fine but while running the whole test file I get the following error

     ** (MatchError) no match of right hand side value: {:error, {:already_started, #PID<0.231.0>}}

I have also turned async: false

I am not using supervisors at the moment hence cant use start_supervised()

That only affects async behaviour between different test files. Tests within a single file are always executed sequentially.

This is not about being a supervisor, but about children of supervisors. I doubt your process cannot be used with start_supervised, unless you’ve build your own process loop and such.

This might be a race condition, as after a test is done the next one is started immediatly, as there’s nothing waiting for the external process to first shutdown correctly.

Thanks for this info :slight_smile:

yeah, this is what I think as well. Is there a way to ensure that the Process has stopped and then go for the next test ?

i think this can be the perfect solution