【问题标题】:Phoenix Controller Testing for Uniqueness Not WorkingPhoenix 控制器唯一性测试不起作用
【发布时间】:2016-07-17 00:09:17
【问题描述】:

我的用户表中的用户名和电子邮件都有一个标准的唯一性约束。现在,我正在测试我的 UserController 在用户创建过程中是否存在重复,我的模型上的 unique_constraint 在单元测试期间似乎不起作用,但在手动测试中却很好。我在这里做错了什么?

迁移:

defmodule MyApi.Repo.Migrations.CreateUser do
  use Ecto.Migration

  def change do
    create table(:users) do
      add :username, :string, null: false
      add :email, :string, null: false
      add :password, :string, null: false
      add :first_name, :string, null: false
      add :last_name, :string, null: false

      timestamps
    end

    create unique_index(:users, [:username])
    create unique_index(:users, [:email])
  end
end

控制器:

defmodule MyApi.V1.UserController do
  use MyApi.Web, :controller

  alias MyApi.User

  def create(conn, %{"data" => data}) do
    user_attrs = JaSerializer.Params.to_attributes(data)
    user_changeset = User.changeset(%User{}, user_attrs)

    case Repo.insert(user_changeset) do
      {:ok, user} ->
        conn
        |> put_status(201)
        |> render(:show, data: user)
      {:error, user_changeset} ->
        conn
        |> put_status(500)
        |> render(:errors, data: user_changeset)
    end
  end
end

测试:

...

test "User creation with non-unique username", %{conn: conn} do
    user_changeset = User.changeset(%User{}, @valid_attrs)
    Repo.insert(user_changeset)

    conn = post(conn, v1_user_path(conn, :create), user_params(@valid_attrs))
    response = json_response(conn, 500)

    errors = response["errors"]
    assert errors
    assert Enum.count(errors) == 1

    {:ok, error} = Enum.fetch(errors, 0)
    assert error["title"] == "has already been taken"

    refute Repo.get_by(User, username: "name1")
end
...

混合测试

1) test User creation with non-unique username (MyApi.V1.UserControllerTest)
     test/controllers/v1/user_controller_test.exs:57
     ** (RuntimeError) expected response with status 500, got: 201, with body:
     {"jsonapi":{"version":"1.0"},"data":{"type":"user","id":"269","attributes":{"username":"name1","last-name":"lastname1","first-name":"first","email":"first@email.com"}}}
     stacktrace:
       (phoenix) lib/phoenix/test/conn_test.ex:362: Phoenix.ConnTest.response/2
       (phoenix) lib/phoenix/test/conn_test.ex:408: Phoenix.ConnTest.json_response/2
       test/controllers/v1/user_controller_test.exs:61: (test)

【问题讨论】:

  • Repo.insert(user_changeset) 行返回什么?您确定测试数据库已正确迁移吗? (尝试删除并重新创建测试数据库)
  • 我尝试了mix ecto.drop(创建|迁移),但问题仍然存在。 {:ok, %SymvelApi.User{__meta__: #Ecto.Schema.Metadata<:loaded, "users">, email: "juan1@gov.ph", first_name: "Juan", id: 276, inserted_at: #Ecto.DateTime<2016-07-16 15:51:01>, last_name: "Dela Cruz", password: "$2b$04$dXmutZbRrrsCd0JaLh.p3uJlIuNf6DVqR3Wz0vR1l5ubBfL3ea03y", updated_at: #Ecto.DateTime<2016-07-16 15:51:01>, username: "juan1"}}
  • 你用MIX_ENV=test运行了那些?
  • @Dogbert 哇。解决了它。传奇。我怎样才能把你的答案作为更正的答案?
  • 作为答案发布。 :)

标签: elixir phoenix-framework ecto


【解决方案1】:

如果您在创建迁移后运行mix test,然后编辑同一迁移以添加unique_index 调用,您的数据库将不会自动迁移到同一迁移的新版本。

有两种解决方案:

  1. 创建一个单独的迁移,将unique_index 添加到表中。

    您的测试数据库将在您下次运行mix test 时自动迁移。

  2. 手动删除/创建或回滚/迁移(如果这是您最近的迁移)测试数据库:

    要么:

    MIX_ENV=test mix do ecto.drop, ecto.create, ecto.migrate
    

    或(如果这是您最近的迁移):

    MIX_ENV=test mix do ecto.rollback, ecto.migrate
    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-27
    相关资源
    最近更新 更多