Real-Time Phoenix: ProductChannelTest - undefined function describe/2 (pg 203)

Hi,

I am getting an error I cannot figure out on my test.
I have what I think is the exact code from the book, other than I changed “use” to “import” to fix a deprecation warning:

defmodule Sneakers23Web.ProductChannelTest do

  #use Sneakers23Web.ChannelCase, async: true
  import Sneakers23Web.ChannelCase
  alias Sneakers23Web.{Endpoint, ProductChannel}
  alias Sneakers23.Inventory.CompleteProduct

  describe "notify product released" do
    test "the size selector for the product is broadcast" do
      {inventory, _data} = Test.Factory.InventoryFactory.complete_products()
      [_, product] = CompleteProduct.get_complete_products(inventory)

      topic = "product:#{id}"
      Endpoint.subscribe(topic)

      ProductChannel.notify_product_released(product)

      assert_broadcast "released", %{size_html: html}

      assert html =~ "size-container__entry"

      Enum.each(product.items, fn item ->
        assert html =~ ~s(value="#{item.id}")
      end)
    end
  end
end

The error I get is:

sneakers_23 % mix test

12:57:13.705 [info] Migrations already up

== Compilation error in file test/sneakers_23_web/product_channel_test.exs ==
** (CompileError) test/sneakers_23_web/product_channel_test.exs:8: undefined function describe/2
(stdlib 3.15.2) erl_eval.erl:685: :erl_eval.do_apply/6
(elixir 1.12.1) lib/kernel/parallel_compiler.ex:428: Kernel.ParallelCompiler.require_file/2
(elixir 1.12.1) lib/kernel/parallel_compiler.ex:321: anonymous fn/4 in Kernel.ParallelCompiler.spawn_workers/7

I can imagine why describe would not show up if I am not importing the right test module, but why is it saying I have describe/2 when I am clearly only giving it one argument? Changing import back to use doesn’t fix anything either.

Hi, you must use the ChannelCase because that brings in the macros and other functions required.

What error do you get when you use it?

If I do use I get the deprecation warning about use, and a slightly different error, it doesn’t find test/2:

Here is the entire module:

defmodule Sneakers23Web.ProductChannelTest do

  use Sneakers23Web.ChannelCase, async: true
  #import Sneakers23Web.ChannelCase
  alias Sneakers23Web.{Endpoint, ProductChannel}
  alias Sneakers23.Inventory.CompleteProduct

  describe "notify product released" do
    test "the size selector for the product is broadcast" do
      {inventory, _data} = Test.Factory.InventoryFactory.complete_products()
      [_, product] = CompleteProduct.get_complete_products(inventory)

      topic = "product:#{product.id}"
      Endpoint.subscribe(topic)

      ProductChannel.notify_product_released(product)

      assert_broadcast "released", %{size_html: html}

      assert html =~ "size-container__entry"

      Enum.each(product.items, fn item ->
        assert html =~ ~s(value="#{item.id}")
      end)
    end
  end
end

running the test:

mix test

14:09:08.826 [info] Migrations already up
…warning: Using Phoenix.ChannelTest is deprecated, instead of:

use Phoenix.ChannelTest

do:

import Phoenix.ChannelTest

test/sneakers_23_web/product_channel_test.exs:3: Sneakers23Web.ProductChannelTest (module)


== Compilation error in file test/sneakers_23_web/views/error_view_test.exs ==
** (CompileError) test/sneakers_23_web/views/error_view_test.exs:17: undefined function test/2
(stdlib 3.15.2) erl_eval.erl:685: :erl_eval.do_apply/6
(elixir 1.12.1) lib/kernel/parallel_compiler.ex:428: Kernel.ParallelCompiler.require_file/2
(elixir 1.12.1) lib/kernel/parallel_compiler.ex:321: anonymous fn/4 in Kernel.ParallelCompiler.spawn_workers/7

These are the libraries I am using:

defp deps do
    [
      {:phoenix, "~> 1.6.0"},
      {:phoenix_pubsub, "~> 2.0.0"},
      {:phoenix_ecto, "~> 4.4.0"},
      {:ecto_sql, "~> 3.7.2"},
      {:postgrex, ">= 0.0.0"},
      {:phoenix_html, "~> 3.2.0"},
      {:phoenix_live_reload, "~> 1.3.3", only: :dev},
      {:gettext, "~> 0.11"},
      {:jason, "~> 1.0"},
      {:plug_cowboy, "~> 2.0"}
    ]
  end

Ah, open up test/support/channel_case.ex and change the code there. You’ll see use Phoenix.ChannelTest is currently there.

You are likely using the newest Phoenix. There aren’t a ton of differences, but some minor things may pop up, like PubSub setup. If you pin the Phoenix version, you’ll get things working for sure.

Ok so I changed the use to import in channel_case.ex but no difference.
I had initially updated to phoenix-1.6 because I am working through a few different books and wanted them all to be on the latest version for my own sanity but also I thought it would be useful to learn how to upgrade a project, but if I give up on that notion and set the versions to what they were, I get af PubSub configuration error

** (Mix) Could not start application sneakers_23: Sneakers23.Application.start(:normal, ) returned an error: shutdown: failed to start child: Sneakers23Web.Endpoint
** (EXIT) shutdown: failed to start child: Phoenix.PubSub.PG2
** (EXIT) shutdown: failed to start child: Phoenix.PubSub.PG2Server
** (EXIT) an exception was raised:
** (UndefinedFunctionError) function :pg2.create/1 is undefined or private
(kernel 8.0.2) :pg2.create({:phx, Sneakers23.PubSub})
(phoenix_pubsub 1.1.2) lib/phoenix/pubsub/pg2_server.ex:43: Phoenix.PubSub.PG2Server.init/1
(stdlib 3.15.2) gen_server.erl:423: :gen_server.init_it/2
(stdlib 3.15.2) gen_server.erl:390: :gen_server.init_it/6
(stdlib 3.15.2) proc_lib.erl:226: :proc_lib.init_p_do_apply/3

which I think was the reason I upgraded everything in the first place because this post

Ah, that’s due to the Erlang version. You are right to upgrade it if you’re following with other books.

I’m unsure of the problem you’re facing because changed the use to import in channel_case.ex but no difference is not correct. When you change from use to import there, that warning will disappear.

I’m unable to provide updated code for the book because that has to go through a process with the publisher. I’m willing to evaluate my options for providing a code-update, but I need to get their thoughts here.

What about this: you upload your warning code (not the one with :pg2 failing) to Github and I’ll update it to work with latest Erlang/Elixir without warnings. I cannot do every chapter’s code, but I can do it for the current code you’re stuck on. It is likely something you can then apply to other chapters.

Hmm well everything seems to be working now, I did change the PubSub config as suggested by the compiler and the use to import in the macro . I was getting some other weird errors but I deleted _build and recompiled and that seemed to fix it, so I guess no action is required, thanks!

Commit: cda002dc4b8cb339699cbb7e74d821ed1e558039

Edit: I think this was all caused by my having two installs of Elixir, at some point while working on a different project I installed asdf and didn’t uninstall the original eliixir, which might explain why the _build directory was in an inconsistent state.
So you are right, it was due to erlang version conflict and not the code’s fault.