For my elixir project I have a following subscription in my lib/graphql_user_web/schema/subscriptions/user.ex
:
defmodule GraphqlUserWeb.Schema.Subscriptions.User do
use Absinthe.Schema.Notation
object :user_subscriptions do
field :created_user, :user do
trigger :create_user, topic: fn _ ->
"new_user"
end
config fn _, _ ->
{:ok, topic: "new_user"}
end
end
end
end
So far it has been working well on localhost:4000/graphiql.
I just want to add unit test for it.
Here's my setup of ChannelCase
in test/support/channel_case.ex
:
defmodule GraphqlUserWeb.ChannelCase do
use ExUnit.CaseTemplate
using do
quote do
use Phoenix.ChannelTest
import Absinthe.Phoenix.SubscriptionTest
@endpoint GraphqlUserWeb.Endpoint
end
end
setup tags do
:ok = Ecto.Adapters.SQL.Sandbox.checkout(GraphqlUser.Repo)
unless tags[:async] do
Ecto.Adapters.SQL.Sandbox.mode(GraphqlUser.Repo, {:shared, self()})
end
{:ok, socket} = Phoenix.ChannelTest.connect(GraphqlUserWeb.UserSocket, %{})
{:ok, socket: Absinthe.Phoenix.SubscriptionTest.join_absinthe(socket)}
end
end
And here's my SubscriptionCase
setup in test/support/subscription_case.ex
:
defmodule GraphqlUserWeb.SubscriptionCase do
use ExUnit.CaseTemplate
using do
quote do
import Phoenix.ChannelTest
use GraphqlUserWeb.ChannelCase
use Absinthe.Phoenix.SubscriptionTest,
schema: GraphqlUserWeb.Schema
setup tags do
{:ok, socket} = Phoenix.ChannelTest.connect(GraphqlUserWeb.Endpoint, %{})
{:ok, socket: Absinthe.Phoenix.SubscriptionTest.join_absinthe(socket)}
{:ok, %{socket: socket}}
end
end
end
end
And I have a pretty simple/basic test in test/graphql_user_web/schema/subscriptions/user_test.ex
:
defmodule GraphqlUserWeb.SubscriptionTest do
use GraphqlUserWeb.SubscriptionCase
alias GraphqlUser.Factory
describe "user subscriptions" do
setup do
{:ok, user: Factory.insert(:user)}
end
test "receives a created_user subscription event", %{socket: socket} do
# Subscribe to the "created_user" subscription
ref = push_doc(socket, """
subscription {
createdUser {
id
name
email
}
}
""")
assert_reply ref, :ok, reply
IO.inspect(reply)
end
end
end
The test basically cannot run and throws error:
1) test user subscriptions receives a created_user subscription event (GraphqlUserWeb.SubscriptionTest)
test/graphql_user_web/schema/subscriptions/user_test.exs:11
** (UndefinedFunctionError) function Phoenix.ChannelTest.connect/2 is undefined or private. However, there is a macro with the same name and arity. Be sure to require Phoenix.ChannelTest if you intend to invoke this macro
stacktrace:
(phoenix 1.7.18) Phoenix.ChannelTest.connect(GraphqlUserWeb.UserSocket, %{})
(graphql_user 0.1.0) test/support/channel_case.ex:20: GraphqlUserWeb.ChannelCase.__ex_unit_setup_0/1
(graphql_user 0.1.0) test/support/channel_case.ex:1: GraphqlUserWeb.ChannelCase.__ex_unit__/2
test/graphql_user_web/schema/subscriptions/user_test.exs:1: GraphqlUserWeb.SubscriptionTest.__ex_unit__/2
I tried doing import Phoenix.ChannelTest
instead of use Phoenix.ChannelTest
. Still same error.
Can anyone point out where I'm being dumb? Thanks! I think it's my setup of ChannelCase
and/or SubscriptionCase
.
TLDR: you should add the following:
defmodule GraphqlUserWeb.ChannelCase do
use ExUnit.CaseTemplate
require Phoenix.ChannelTest # <= here
using do
As for the longer explanation, there are two different lexical scopes at work here:
ChannelCase
, which was calling a macro from Phoenix.ChannelTest
so it needs to require
it firstSubscriptionTest
or any module using ChannelCase
, which is where ChannelCase
's using
block will be expandeduse
is for injecting code in other modules, but it won't affect the module defining the code being injected.