Reputation: 16761
I'm building a elixir phoenix app using a custom database adapter to connect to OrientDB. So I generated the base app with the --no-ecto
option since I'm not using Ecto.
I'm building custom models and custom validations but of course want to do unit testing.
If I try to include ModelCase in my unit tests like so:
defmodule App.UserTest do
use App.ModelCase
end
I get the error
module App.ModelCase is not loaded and could not be found
Which is probably because it is part of Ecto.
If I don't include it, the code fails later, telling me that
undefined function test/2
How can I deal with that?
Upvotes: 5
Views: 3559
Reputation: 9299
Short answer: instead of use App.ModelCase
just use use ExUnit.Case
.
Long answer. When creating project with Ecto you get three different test case templates located in test/support
:
Case templates are used to define functions that can be used in every test that uses the template.
For example the model_case
defines this for you:
using do
quote do
alias App.Repo
import Ecto
import Ecto.Changeset
import Ecto.Query, only: [from: 1, from: 2]
import App.ModelCase
end
end
setup tags do
unless tags[:async] do
Ecto.Adapters.SQL.restart_test_transaction(App.Repo, [])
end
:ok
end
def errors_on(model, data) do
model.__struct__.changeset(model, data).errors
end
Everything inside quote do ... end
is injected at the beginning of your test case. This not useful at all if you are not using Ecto. First line aliases repo, next lines import Ecto modules (which you don't have)
Setup function makes sure that tests are run inside transaction that can be rolled back when they finish and errors_on
is also Ecto specific. That is why this module is not present at all when you run with --no-ecto
.
So you have two options. You can either just use ExUnit.Case
which is standard way of dealing with tests (you can check that by creating non-Phoenix application with mix) or you can create your own App.ModelCase
. This might be a good idea if there is enough shared code between your model test cases.
Upvotes: 5
Reputation: 8280
App.ModelCase
is not automatically generated with the --no-ecto
option.
It itself does use ExUnit.CaseTemplate
(See the CaseTemplate docs),
and injects an import App.ModelCase
into the using module. It also imports some ecto-specific modules, but they're not useful to you.
In your case, you can define App.ModelCase
in test/support/model_case
, use ExUnit.CaseTemplate
inside it, and define what you want injected into the using module by defining a using
macro.
Just to give you an idea of some of the things you might want to do, here's an example ecto-specific version:
defmodule App.ModelCase do
use ExUnit.CaseTemplate
using do
quote do
alias App.Repo
import Ecto
import Ecto.Changeset
import Ecto.Query, only: [from: 1, from: 2]
import App.ModelCase
end
end
setup tags do
# Setup stuff you want to automatically do before tests
end
def some_helper_function
# helper function stuff goes here
#
# this function is available in all using modules because of
# the `import App.ModelCase` in the using macro.
end
end
So either:
or just use ExUnit.Case
instead of use App.ModelCase
. Either way should work.
use ExUnit.Case
is simpler. use App.ModelCase
will allow you to define helpers that are available in all using modules.
Upvotes: 1