#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
здесь.
Пожалуйста, дайте мне знать, если это вам как-то поможет. 😉