在测试控制器时,在测试数据库中包含一些数据会很有用。有时您可能想要测试数据创建。设置它的正确方法是什么?对控制器的测试应该测试控制器的create
功能是否正常,而不是模型。
作为一个例子,我想测试一个Session控制器,我有两个测试。一个是测试创建的用户是否可以登录。另一个是,如果密码错误,他就不能。两者都依赖于用户在数据库中。我现在如何处理它是首先创建用户:
defmodule MyApp.SessionControllerTest do
use MyApp.ConnCase
alias MyApp.Admin
@valid_attrs %{email: "email@example.com", name: "John Doe", password: "goodpassword", password_confirmation: "goodpassword", password_hash: "somecontent", username: "username"}
@invalid_attrs %{}
setup do
{:ok, conn: put_req_header(conn, "accept", "application/json")}
end
test "admin can login after creation" do
conn = post conn, admin_path(conn, :create), admin: @valid_attrs
body = json_response(conn, 201)
assert Repo.get_by(Admin, email: @valid_attrs[:email])
conn = post conn, session_path(conn, :create), %{data: %{attributes: %{email: @valid_attrs[:email], password: @valid_attrs[:password]}}}
body = json_response(conn, 201)
assert body["data"]["token"]
end
test "login with wrong password returns an error" do
conn = post conn, session_path(conn, :create), %{data: %{attributes: %{email: @valid_attrs[:email], password: "wrongpassword"}}}
body = json_response(conn, 403)
assert body["error"]
end
end
如果我现在在我的Admin
模型上添加唯一性限制,这可能会变得混乱,因为每当我需要数据库中的用户时,我必须确保测试不会因为这个约束而失败但是因为测试控制器中的某些东西是错误的。此外,还不清楚测试运行的顺序,并且在几次测试中与数据创建保持一致似乎是一场噩梦。
我要么想要一个我在开始时定义创建数据的地方。或者使用模拟进行控制器测试。
这怎么可能?
答案 0 :(得分:10)
使用setup
功能将一些数据添加到数据库中。
setup do
Repo.insert!(%User{id: 1, password: "somepassword", ....})
....
:ok
end
每次测试前都会调用setup
。
有关详细信息,请参阅ExUnit hexdocs。
要在同步模式下逐步运行测试,请添加async: false
以使用呼叫。
defmodule MyApp.SessionControllerTest do
use MyApp.ConnCase, async: false`
但我认为最好在不依赖其他测试的情况下运行测试。
defmodule MyApp.SessionControllerTest do
use MyApp.ConnCase
alias MyApp.Admin
@valid_attrs %{email: "email@example.com", name: "John Doe", password: "goodpassword", password_confirmation: "goodpassword", password_hash: "somecontent", username: "username"}
@invalid_attrs %{}
setup do
Repo.insert!(%User{email: "bar@example.com", password: "somepassword", ....})
{:ok, conn: put_req_header(conn, "accept", "application/json")}
end
...
test "login with wrong password returns an error" do
conn = post conn, session_path(conn, :create), %{data: %{attributes: %{email: "bar@example.com", password: "wrongpassword"}}}
body = json_response(conn, 403)
assert body["error"]
end
end
希望它有所帮助。
答案 1 :(得分:2)
派对有点晚,但可能对其他人有所帮助。
我建议使用ex_machina工厂库。 https://github.com/thoughtbot/ex_machina 有了它,您可以在一个地方定义和创建测试数据。
像这样定义工厂:
defmodule MyApp.Factory do
# with Ecto
use ExMachina.Ecto, repo: MyApp.Repo
# without Ecto
use ExMachina
def user_factory do
%MyApp.User{
name: "Jane Smith",
email: sequence(:email, &"email-#{&1}@example.com"),
}
end
def article_factory do
%MyApp.Article{
title: "Use ExMachina!",
# associations are inserted when you call `insert`
author: build(:user),
}
end
def comment_factory do
%MyApp.Comment{
text: "It's great!",
article: build(:article),
}
end
end
创建记录将是:
insert(:comment, article: article)
您还可以构建记录(未保存)
build(:user)