2016-07-16 81 views
1

我有我的用戶表中的用戶名和電子郵件的標準唯一性約束。現在,我正在測試用戶創建期間我的用戶控制器的重複情況,似乎我的模型上的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":"[email protected]"}}} 
    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) 
+0

行'Repo.insert(user_changeset)'返回什麼?你確定測試數據庫是否正確遷移? (嘗試刪除並重新創建測試數據庫) – Dogbert

+0

我嘗試過'mix ecto.drop'(create | migrate),問題仍然存在。 '{:ok, %SymvelApi.User {__ meta__:#Ecto.Schema.Metadata <:loaded,「users」>, email:「[email protected]」,first_name:「Juan」,id:276 , inserted_at:#Ecto.DateTime <2016年7月16日15時51分01秒>,姓氏: 「帝拉庫茲」, 密碼: 「$ $ 2B 04 $ dXmutZbRrrsCd0JaLh.p3uJlIuNf6DVqR3Wz0vR1l5ubBfL3ea03y」, 的updated_at:#Ecto.DateTime <2016 -07-16 15:51:01>,用戶名:「juan1」}}' – Neil

+0

你用'MIX_ENV = test'運行了那些嗎? – Dogbert

回答

2

如果在創建遷移後跑mix test,然後編輯相同的遷移,添加unique_index電話,你的數據庫不會被自動遷移到同一遷移的新版本。

有2級的解決方案:

  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