rspec + shoulda: 设置数据
rspec + shoulda: setting up data
我有以下测试。共有三个 it
块。与其他两个不同,第一个不使用 shoulda
。
如果我不将 before
块与 post :create, product: attrs
一起使用,那么第一个测试会按预期失败。但是如果我把 before
块放在那里,那么第一个测试失败,但其他两个通过。我对产品名称进行了唯一性验证,但这不应该是问题,因为我正在使用工厂序列。
我该怎么办?当同时存在 rspec 和 shoulda 匹配器时,我通常应该如何设置测试数据?
describe "when user logged in" do
before(:each) do
login_user #logged in user is available by calling @user
end
context "POST create" do
context "with valid attributes" do
let!(:profile) { create(:profile, user: @user) }
let!(:industry) { create(:industry) }
let!(:attrs) { attributes_for(:product, user_id: @user.id, industry_ids: [ industry.id ]).merge(
product_features_attributes: [attributes_for(:product_feature)],
product_competitions_attributes: [attributes_for(:product_competition)],
product_usecases_attributes: [attributes_for(:product_usecase)]
) }
it "saves the new product in the db" do
expect{ post :create, product: attrs }.to change{ Product.count }.by(1)
end
#If I don't use this the 2 tests below fail. If I use it, then the test above fails.
# before do
# post :create, product: attrs
# end
it { is_expected.to redirect_to product_path(Product.last) }
it { is_expected.to set_flash.to('Product got created!') }
end
end
end
工厂
factory :product, class: Product do
#name { Faker::Commerce.product_name }
sequence(:name) { |n| "ABC_#{n}" }
company { Faker::Company.name }
website { 'https://example.com' }
oneliner { Faker::Lorem.sentence }
description { Faker::Lorem.paragraph }
user
end
你不能两全其美。如果你在 before
中执行你正在测试的方法,那么你不能再次执行它来查看它是否改变了 Product
计数。如果您之前不执行它,那么您必须在您的示例中执行它,因此不能使用 is_expected
单行格式。
有多种选择。这是一个将方法的执行合并到所有示例中的方法。
describe "when user logged in" do
before(:each) do
login_user #logged in user is available by calling @user
end
describe "POST create" do
subject(:create) { post :create, product: attrs }
context "with valid attributes" do
let!(:profile) { create(:profile, user: @user) }
let!(:industry) { create(:industry) }
let!(:attrs) { attributes_for(:product, user_id: @user.id, industry_ids: [ industry.id ]).merge(
product_features_attributes: [attributes_for(:product_feature)],
product_competitions_attributes: [attributes_for(:product_competition)],
product_usecases_attributes: [attributes_for(:product_usecase)]
) }
it "saves the new product in the db" do
expect{ create }.to change{ Product.count }.by(1)
end
it("redirects") { expect(create).to redirect_to product_path(Product.last) }
it("flashes") { expect(create).to set_flash.to('Product got created!') }
end
end
end
我有以下测试。共有三个 it
块。与其他两个不同,第一个不使用 shoulda
。
如果我不将 before
块与 post :create, product: attrs
一起使用,那么第一个测试会按预期失败。但是如果我把 before
块放在那里,那么第一个测试失败,但其他两个通过。我对产品名称进行了唯一性验证,但这不应该是问题,因为我正在使用工厂序列。
我该怎么办?当同时存在 rspec 和 shoulda 匹配器时,我通常应该如何设置测试数据?
describe "when user logged in" do
before(:each) do
login_user #logged in user is available by calling @user
end
context "POST create" do
context "with valid attributes" do
let!(:profile) { create(:profile, user: @user) }
let!(:industry) { create(:industry) }
let!(:attrs) { attributes_for(:product, user_id: @user.id, industry_ids: [ industry.id ]).merge(
product_features_attributes: [attributes_for(:product_feature)],
product_competitions_attributes: [attributes_for(:product_competition)],
product_usecases_attributes: [attributes_for(:product_usecase)]
) }
it "saves the new product in the db" do
expect{ post :create, product: attrs }.to change{ Product.count }.by(1)
end
#If I don't use this the 2 tests below fail. If I use it, then the test above fails.
# before do
# post :create, product: attrs
# end
it { is_expected.to redirect_to product_path(Product.last) }
it { is_expected.to set_flash.to('Product got created!') }
end
end
end
工厂
factory :product, class: Product do
#name { Faker::Commerce.product_name }
sequence(:name) { |n| "ABC_#{n}" }
company { Faker::Company.name }
website { 'https://example.com' }
oneliner { Faker::Lorem.sentence }
description { Faker::Lorem.paragraph }
user
end
你不能两全其美。如果你在 before
中执行你正在测试的方法,那么你不能再次执行它来查看它是否改变了 Product
计数。如果您之前不执行它,那么您必须在您的示例中执行它,因此不能使用 is_expected
单行格式。
有多种选择。这是一个将方法的执行合并到所有示例中的方法。
describe "when user logged in" do
before(:each) do
login_user #logged in user is available by calling @user
end
describe "POST create" do
subject(:create) { post :create, product: attrs }
context "with valid attributes" do
let!(:profile) { create(:profile, user: @user) }
let!(:industry) { create(:industry) }
let!(:attrs) { attributes_for(:product, user_id: @user.id, industry_ids: [ industry.id ]).merge(
product_features_attributes: [attributes_for(:product_feature)],
product_competitions_attributes: [attributes_for(:product_competition)],
product_usecases_attributes: [attributes_for(:product_usecase)]
) }
it "saves the new product in the db" do
expect{ create }.to change{ Product.count }.by(1)
end
it("redirects") { expect(create).to redirect_to product_path(Product.last) }
it("flashes") { expect(create).to set_flash.to('Product got created!') }
end
end
end