diff --git a/config/test.exs b/config/test.exs index e7da6b4..d2d855e 100644 --- a/config/test.exs +++ b/config/test.exs @@ -1,3 +1 @@ use Mix.Config - -config :example, service: Example.MockService diff --git a/lib/example/worker.ex b/lib/example/worker.ex index aed9473..6578aa8 100644 --- a/lib/example/worker.ex +++ b/lib/example/worker.ex @@ -3,13 +3,7 @@ defmodule Example.Worker do alias Example.DefaultService - # When using ElixirLS, defining the service at compile time will result in an - # error because ElixirLS always compiles using MIX_ENV=test which mean @service - # will always be set to MockService, which does not have `foo/0` - # @service Application.get_env(:example, :service, DefaultService) - # @service DefaultService - - def service() do + def service do Application.get_env(:example, :service, DefaultService) end @@ -23,24 +17,12 @@ defmodule Example.Worker do def init(_init_arg) do initial_state = "no foo for you" + {:ok, initial_state, {:continue, :get_foo_from_service}} end def handle_continue(:get_foo_from_service, _state) do - # And here lies the problem. We want to call our service to get - # whatever inital state it provides, but in doing so, we break - # in the test environment because the MockService doesn't have - # a function called `foo/0` until it can be defined in the expects - # block within the test - by that time, this code has already - # been executed because this GenServer is part of the staticly - # defined supervision tree in `application.ex`. - - value_of_foo = - if function_exported?(service(), :foo, 0) do - service().foo() - else - "#{inspect(service())} does not support foo" - end + value_of_foo = service().foo() {:noreply, value_of_foo} end diff --git a/test/support/mock_service.ex b/test/support/mock_service.ex deleted file mode 100644 index ec7ee1b..0000000 --- a/test/support/mock_service.ex +++ /dev/null @@ -1,11 +0,0 @@ -# With a hard coded mock like this we can define the behaviour -# before the application starts up, but do we even need Mox at -# this point? -# -# defmodule Example.MockService do -# @behaviour Example.ServiceBehaviour -# -# def foo() do -# "hard coded says foo" -# end -# end diff --git a/test/support/test1_example.ex b/test/support/test1_example.ex new file mode 100644 index 0000000..8992c0c --- /dev/null +++ b/test/support/test1_example.ex @@ -0,0 +1,7 @@ +defmodule Test1Service do + @behaviour Example.ServiceBehaviour + + def foo() do + "test 1 says foo" + end +end diff --git a/test/support/test2_example.ex b/test/support/test2_example.ex new file mode 100644 index 0000000..3a20623 --- /dev/null +++ b/test/support/test2_example.ex @@ -0,0 +1,7 @@ +defmodule Test2Service do + @behaviour Example.ServiceBehaviour + + def foo() do + "test 2 says moo" + end +end diff --git a/test/worker_test.exs b/test/worker_test.exs index b734bfd..073b61a 100644 --- a/test/worker_test.exs +++ b/test/worker_test.exs @@ -1,33 +1,30 @@ defmodule Example.WorkerTest do use ExUnit.Case - import Mox alias Example.Worker - describe "default service" do - test "returns default service foo" do - assert Worker.get_foo() =~ ~s(default says foo) - end + # In order to have the Worker use the test services we need to restart + # the process; killing it will suffice as it is a supervised process + def restart_worker() do + pid = Process.whereis(Worker) + Process.exit(pid, :kill) + Process.sleep(10) end describe "mocked service" do - setup do - # Normally you would add this to `test_helper.ex`, or `support/mocks.ex - Mox.defmock(Example.MockService, for: Example.ServiceBehaviour) + test "returns mocked service foo" do + Application.put_env(:example, :service, Test1Service) - Example.MockService - |> expect(:foo, fn -> "setup all says foo" end) + restart_worker() - :ok + assert Worker.get_foo() =~ ~s(test 1 says foo) end - setup :verify_on_exit! + test "returns mocked service moo" do + Application.put_env(:example, :service, Test2Service) - test "returns mocked service foo" do - Example.MockService - |> expect(:foo, fn -> "mock says foo" end) - |> allow(self(), Process.whereis(Worker)) + restart_worker() - assert Worker.get_foo() =~ ~s(mock says foo) + assert Worker.get_foo() =~ ~s(test 2 says moo) end end end