Ошибка Rspec из-за того, что имя уже занято

#ruby-on-rails #ruby #rspec

#ruby-on-rails #ruby #rspec

Вопрос:

Я пытаюсь создать тестовые наборы rspec. Но ошибка Rspec из-за того, что имя уже занято.

Кажется, что «let» вычисляется при каждом вызове «product».

Как я могу это исправить?

Консоль

 ./spec/models/spree/product_decorator_spec.rb:31:in `block (4 levels) in <top (required)>'

ActiveRecord::RecordInvalid: Validation failed: Name has already been taken
./spec/models/spree/product_decorator_spec.rb:6:in `block (3 levels) in <top (required)>'
./spec/models/spree/product_decorator_spec.rb:20:in `block (4 levels) in <top (required)>'
./spec/models/spree/product_decorator_spec.rb:23:in `block (4 levels) in <top (required)>'

ActiveRecord::RecordInvalid: Validation failed: Name has already been taken
./spec/models/spree/product_decorator_spec.rb:6:in `block (3 levels) in <top (required)>'
./spec/models/spree/product_decorator_spec.rb:12:in `block (4 levels) in <top (required)>'
./spec/models/spree/product_decorator_spec.rb:15:in `block (4 levels) in <top (required)>'
  

product_decorator_spec.rb

 require 'spec_helper'

describe Spree::Product do

  context '#create' do
    let(:us) { create(:zone, name: "US") }
    let(:china) { create(:zone, name: "China") }
    let(:japan) { create(:zone, name: "Japan") }


    context "when a product has no ng zone" do
      let(:product) { create(:product, zones: [us, china, japan]) }

      it "should get ng_zones correctly" do
        product.ng_zones.should match_array []
      end
    end

    context "when a product has one ng zone" do
      let(:product) { create(:product, zones: [us, china]) }

      it "should get ng_zones correctly" do
        product.ng_zones.should match_array ["Japan"]
      end
    end

    context "when a product has two ng zone" do
      let(:product) { create(:product, zones: [us]) }

      it "should get ng_zones correctly" do
        product.ng_zones.should match_array ["China", "Japan"]
      end
    end
  end
end
  

Комментарии:

1. кажется, ваша тестовая база данных не очищается после каждой спецификации. и у вас есть проверка уникальности имени зоны в вашей модели.

2. Проходят ли тесты, когда вы запускаете их по отдельности?

3. Вы должны показать нам соответствующую часть вашего декоратора продукта и его проверки. Вы также могли бы попытаться убедиться, что вы можете создать продукт в rails console с помощью вызова, который вы пытаетесь выполнить.

Ответ №1:

Тело let вычисляется с каждым it блоком. Я предполагаю, что у вас есть ограничение уникальности для ваших Zone классов.

У вас есть 2 возможности

  • Либо создайте переменные в before(:all) блоке и присвоите им что-то вроде @us
  • Очистите свою базу данных after(:each)

Ответ №2:

Вы тестируете Product#create so, вам не нужно будет создавать zones для этого конкретного теста.

Вместо этого вы могли бы просто использовать build_stubbed метод.

 let(:us) { build_stubbed(:zone, name: "US") }
let(:china) { build_stubbed(:zone, name: "China") }
let(:japan) { build_stubbed(:zone, name: "Japan") }
  

Таким образом, процесс создания не будет зависеть от базы данных, а также от проверок для Zone модели, и вы получите потрясающий прирост производительности, поскольку вы не обращаетесь к базе данных для каждого отдельного теста.

Вы можете прочитать об этом build_stubbed здесь.

Пожалуйста, дайте мне знать, если это вам как-то поможет. 😉