rails minitest сводит меня с ума с помощью PG :: UniqueViolation ошибки - PullRequest
0 голосов
/ 24 мая 2018

Половину времени я смогу запустить мои тесты.В другой половине они терпят неудачу из-за нарушения уникальности, источник которого я не могу найти.Прямо сейчас я во второй половине.Моя ошибка такова:

ItemTest#test_valid_setup:
ActiveRecord::RecordNotUnique: PG::UniqueViolation: ERROR:  duplicate key value violates unique constraint "index_blobs_on_user_id_and_item_id"
DETAIL:  Key (user_id, item_id)=(1, 1) already exists.
: INSERT INTO "blobs" ("user_id", "item_id", "amount", "active", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id"
 test/models/item_test.rb:15:in `setup'

У меня есть factories.rb:

FactoryBot.define do
 factory :user, aliases: [:owner] do
  email "test@test.com"
  username "test"
 end

 factory :item do
  owner
  image { loads file etc... }
  price 100
  ...
 end

 factory :blob, aliases: [:wanted, :collateral] do
  user
  item
  amount 0
  active true
 end
end

Мой item_test.rb

require 'test_helper'
require 'support/database_cleaner'

class ItemTest < Minitest::Test
 def setup
  DatabaseCleaner.start
  #create users
  @user1 = FactoryBot.create(:user, email: "a@pear.com", username: "barnyard")
  @user2 = FactoryBot.create(:user, email: "bo@ichi.com", username: "ponygrl")
  @user3 = FactoryBot.create(:user, email: "ho@ho.com", username: "hon")

  #create items
  @item1 = FactoryBot.create(:item, owner: @user1)
  @item2 = FactoryBot.create(:item, owner: @user2, price: 101)
  @item3 = FactoryBot.create(:item, owner: @user3, price: 102)

  #create blobs
  @blob1 = FactoryBot.create(:blob, user: @user1, item: @item1, amount: @item1.price, active: false)
  @blob2 = FactoryBot.create(:blob, user: @user2, item: @item2, amount: @item2.price, active: false)
  @blob3 = FactoryBot.create(:blob, user: @user3, item: @item3, amount: @item3.price, active: false)
 end

 def teardown
  DatabaseCleaner.clean
 end
end

А затем item.rb

class Item < ApplicationRecord
 after_create :create_blobs

 private
 def create_blobs
  blob = Blob.new(user_id: self.owner.id, item_id: self.id, amount: self.price)
  blob.save
 end
end

Небольшой фон: A User создает Item, который, в свою очередь, создает Blob в after_create с параметром amount, установленным в значение Item.price.Я не могу выяснить, как запустить after_create в minitest, поэтому я смоделировал данные Blob в настройке для наследования от атрибута Item.

. Я вижу, что ошибка происходит из строки 15item_test.rb, но я не понимаю почему.Я создаю Users, затем Items, а затем ОШИБКА Blobs.Я понимаю, почему (у меня есть ограничение уникальности уровня базы данных для комбинации пользователя и элемента), но не как (потому что из того, что я вижу, я не создал эти Blobs - нет after_create, вызываемого на Item когда они созданы в тесте), и я подозреваю, что это связано с тем, как я пишу это.

Мне кажется естественным заключить, что оба DatabaseCleaner.start и DatabaseCleaner.clean начинаютсяи очистить старые тестовые данные, когда тест будет запущен и завершен, но это, очевидно, не так.Я начал использовать его специально, чтобы избежать этой проблемы, которая у меня была ранее.Итак, я db: drop, db: create и db: schema: load, но, опять же, у меня та же проблема.И если это не так, это нарушение уникальности имени пользователя, электронной почты и т. Д. Короче говоря, что происходит с этой ошибкой?

Извините, если это так запутанно.

Редактировать: Если я раскомментирую after_create и заменю все ссылки на методы на объект blob, созданный с помощью этого обратного вызова, на blobs, созданный в моей настройке теста, тесты пройдут.Но мне действительно не нравится это делать.

1 Ответ

0 голосов
/ 24 мая 2018

Либо раскомментируйте after_create и ссылайтесь на тестовые объекты, либо удаляйте тестовые объекты и ссылайтесь на каждый BLOB-объект, написав метод, который возвращает пользователя и элемент BLOB-объекта own_by, чтобы вы могли написать @item.blob и вернуть его.соответствующие blob.

...