2016-09-11 7 views
3

私のデータベースで一意性をテストしようとしていますが、少し問題があります。第二のインサートにもかかわらず、通過しているようだEctoで一意性制約をテストする方法

test "duplicate email changeset is invalid" do 
    %Signup{} 
    |> Signup.changeset(@valid_attrs) 
    |> Repo.insert! 

    user2 = %Signup{} 
    |> Signup.changeset(@valid_attrs) 
    assert {:error, _changeset} = Repo.insert(user2) 
end 

:私のモデルでこのチェンジdefを持つ

def change do 
    create table(:signups) do 
    add :name, :string 
    add :email, :string 

    timestamps() 
    end 

    create unique_index(:signups, [:email]) 
end 

def changeset(struct, params \\ %{}) do 
    struct 
    |> cast(params, [:name, :email]) 
    |> validate_required([:name, :email]) 
    |> validate_format(:email, ~r/@/) 
    |> update_change(:email, &String.downcase/1) 
    |> unique_constraint(:email) 
end 

をし、失敗のテストがある私は、この移行を実行しましたそれはすべきではない。返される正確なエラーは次のとおりです。

1) test duplicate email changeset is invalid (EventSignup.SignupTest) 
    test/models/signup_test.exs:24 
    match (=) failed 
    code: {:error, _changeset} = Repo.insert(user2) 
    rhs: {:ok, 
      %EventSignup.Signup{__meta__: #Ecto.Schema.Metadata<:loaded, "signups">, 
      email: "[email protected]", id: 41, 
      inserted_at: #Ecto.DateTime<2016-09-11 19:35:40>, 
      name: "some content", 
      updated_at: #Ecto.DateTime<2016-09-11 19:35:40>}} 
    stacktrace: 
     test/models/signup_test.exs:31: (test) 

ここでは何が欠けているのですか?私が手動で2つの同じレコードをiex経由で挿入すると、2番目の挿入は失敗しますが、テスト中に通過します。

+1

この制約がテストデータベースに存在していますか?おそらく、制約を追加する前にテストデータベースを移行したでしょうか?テストデータベースを再度削除、作成、移行してみてください( 'MIX_ENV =テストミックスdo ecto.drop、ecto.create、ecto.migrate')、テストを実行してください。 – Dogbert

+1

@Dogbertあなたは正しいです。このエラーは私には別のテストデータベースがあり、標準のミックスecto.rollback、mix ecto.migrateはマイグレーションにユニーク制約を後で追加することをカバーしないことを知らないということから来ました。学んだ教訓。 あなたは最初のことでしたので、これを回答としてお寄せいただければ幸いです。 – targaf

答えて

1

テスト環境MIX_ENV=test iex -S mixでiexを実行し、同じ値の2つのレコードを挿入しようとします。そうすることができれば、テストデータベースにunique_indexが見つからないことを意味します。 重要!後でテストデータベースをきれいにすることを忘れないでください。

または
上記の説明を省略してMIX_ENV=test mix ecto.resetを実行し、もう一度テストを実行してください。彼らがあなたのテストに合格すれば、dbはunique_indexを見つけられませんでした。

+0

btw ecto.resetは[ecto.drop、ecto.create、ecto.migrate]のエイリアスです。 – amatalai

4

マイグレーションとモデルが正しいと思います。しかし、あなたが何かをするときにアサルトマクロに=を使用しているように見えます:

test "duplicate email changeset is invalid" do 
    %Signup{} 
    |> Signup.changeset(@valid_attrs) 
    |> Repo.insert! 

    user2 = %Signup{} 
    |> Signup.changeset(@valid_attrs) 

    {:error, changeset} = Repo.insert(user2) 
    refute changeset.valid? 
end 

ここは私のテストです。

test "only one setting per company" do 
    first_setting = insert(:setting) 
    second_setting = params_for(:setting, %{company_id: first_setting.company.id}) 
    changeset = Setting.changeset(%Setting{}, second_setting) 
    {:error, changeset} = Repo.insert changeset 
    assert changeset.errors == [company_id: {"has already been taken", []}] 
    refute changeset.valid? 
end 

挿入が有効なモデルを作成してのparamsが起こるエラーを強制的に同じのcompany_idと有効なマップを返すex-machinaからのヘルパーメソッドです。

関連する問題