Эликсир / Феникс: Как проводить юнит-тесты моделей без использования Ecto?

Я создаю приложение elixir phoenix, используя специальный адаптер базы данных для подключения к OrientDB. Итак, я создал базовое приложение с опцией --no-ecto, поскольку я не использую Ecto.

Я создаю собственные модели и пользовательские проверки, но, конечно, хочу провести модульное тестирование.

Если я попытаюсь включить ModelCase в свои модульные тесты, например:

defmodule App.UserTest do
  use App.ModelCase

end

Я получаю ошибку

module App.ModelCase is not loaded and could not be found

Вероятно, потому, что он является частью Ecto.

Если я его не добавлю, код позже выйдет из строя, сообщив мне, что

undefined function test/2

Как я могу с этим справиться?


person Ole Spaarmann    schedule 15.04.2016    source источник


Ответы (2)


Краткий ответ: вместо use App.ModelCase просто используйте use ExUnit.Case.

Длинный ответ. При создании проекта с Ecto вы получаете три разных шаблона тестовых случаев, расположенных в test/support:

  • channel_case.ex
  • conn_case.ex
  • model_case.ex

Шаблоны дел используются для определения функций, которые могут использоваться в любом тест, использующий шаблон.

Например, model_case определяет это для вас:

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

Все, что находится внутри quote do ... end, вводится в начале вашего тестового примера. Это совершенно бесполезно, если вы не используете Ecto. Репозиторий псевдонимов первой строки, следующие строки импортируют модули Ecto (которых у вас нет)

Функция настройки гарантирует, что тесты выполняются внутри транзакции, которую можно откатить, когда они завершатся, и errors_on также зависит от Ecto. Вот почему этот модуль вообще отсутствует при запуске с --no-ecto.

Итак, у вас есть два варианта. Вы можете либо просто использовать ExUnit.Case, который является стандартным способом работы с тестами (вы можете проверить это, создав приложение, отличное от Phoenix, с помощью mix), либо вы можете создать свое собственное App.ModelCase. Это может быть хорошей идеей, если между тестовыми примерами вашей модели достаточно общего кода.

person tkowal    schedule 15.04.2016
comment
Похоже, вы сохранили имя своего приложения в блоке unless tags[:async]. Возможно, вы захотите изменить его на App.Repo, чтобы будущие люди не запутались. - person Cody Poll; 16.04.2016
comment
model_case.ex, похоже, был заменен на data_case.ex по крайней мере в Elixir 1.5.2 - person Nayan Hajratwala; 25.11.2017

App.ModelCase не создается автоматически с параметром --no-ecto.

Сам он use ExUnit.CaseTemplate (см. Документацию CaseTemplate) и вводит import App.ModelCase в модуль using. Он также импортирует некоторые модули, специфичные для экто, но они вам не нужны.

В вашем случае вы можете определить App.ModelCase в test/support/model_case, use ExUnit.CaseTemplate внутри него и определить, что вы хотите ввести в модуль using, определив макрос using.

Чтобы дать вам представление о некоторых вещах, которые вы, возможно, захотите сделать, вот пример конкретной экто-версии:

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

Так что либо:

  1. Создайте файл
  2. Удалите то, что не имеет отношения к вашему приложению
  3. Добавьте свой собственный материал

или просто use ExUnit.Case вместо use App.ModelCase. В любом случае должно работать.

use ExUnit.Case проще. use App.ModelCase позволит вам определять помощников, которые доступны во всех используемых модулях.

person Cody Poll    schedule 15.04.2016