When to use async:true in tests

hi everyone

I’m finishing Programming Phoenix 1.4 and in the last chapter there is the following test:

defmodule RumblWeb.Channels.VideoChannelTest do

  use RumblWeb.ChannelCase
  import RumblWeb.TestHelpers

  setup do
    user = insert_user(name: "Gary")
    video = insert_video(user, title: "Testing")
    token = Phoenix.Token.sign(@endpoint, "user socket", user.id)
    {:ok, socket} = connect(RumblWeb.UserSocket, %{"token" => token})

    {:ok, socket: socket, user: user, video: video}
  end

  test "join replies with video annotations", %{socket: socket, video: vid, user: user} do
    for body <- ~w(one two) do
      Rumbl.Multimedia.annotate_video(user, vid.id, %{body: body, at: 0})
    end

    {:ok, reply, socket} = subscribe_and_join(socket, "videos:#{vid.id}", %{})

    assert socket.assigns.video_id == vid.id
    assert %{annotations: [%{body: "one"}, %{body: "two"}]} = reply 
  end
end

The book then proceeds to explain that we’re not using async: true because there are two or more processes talking to the database at the same time.

Note we haven’t passed the async: true flag to the ChannelCase as we did to other cases. Here’s why. In Ecto’s Sandbox mode, every process has its own connection. That’s not a problem in applications that limit database access to a single process. The test case starts a transaction, modifies the database, asserts results and then rolls back the transaction when the test completes.

This application is different. It has two or more processes talking to the database at the same time, in the same test. Because processes might need to acces the same data, the only way for them to share data in the sandbox mode is to share the same connection. To maintain isolation for each test, we can’t run tests concurrently. That means we can’t set async.

Could someone kindly explain which are the 2 or more processes talking to the db at the same time?

Also doesn’t async: true refer to running multiple tests simultaneously (i.e. not processes in the same test, since arbitrary code within test can run async anyways)?

I guess I just can’t grasp how this test is any different from all the others where async: true is used

It is explained here

It is a bit long, but I cannot explain it any better.

1 Like