工厂女孩协会的问题和 let 的使用:
Issue with factory girl association and use of let:
我有一个奇怪的问题。我为 user/deal has_many/has_many 关系创建了一个工厂 user_deals,但似乎 rspec 现在迫使我断言一个用户,即使我不需要一个用户(确实是用户仅记录在我的数据库中,如果网络访问者登录,则在应用程序中需要)
此测试无效:
context "As NON SIGNED-IN visitor" do
describe "HP card has the right content and behavior on small screens (1-column view)", :js => true do
let(:subject) { ApplicationController.new }
let(:deal_for_german_people) { create(:deal_skips_validate,
:country => "Germany",
:title => "title of deal for German people") }
let(:deal_for_german_people2) { create(:deal_skips_validate,
:country => "Germany",
:title => "title 2 of deal for German people") }
before do
resize_window_to_mobile
end
after do
resize_window_default
end
it "plus and minus icons behave correctly" do
visit root_path
# user sees on mobile the little "plus" icon by default
expect(page).to have_css('.card-detail-opener', visible: true)
end
end
但如果我添加 create(:user) 并创建 "user_deals",测试通过。 但我在上下文中 "non signed in user",那么我为什么要创建一个用户和 user_deals 呢?
context "As NON SIGNED-IN visitor" do
describe "HP card has the right content and behavior on small screens (1-column view)", :js => true do
let(:subject) { ApplicationController.new }
let(:user) { create(:user,
user_country_name: 'Germany') }
let(:deal_for_german_people) { create(:deal_skips_validate,
:country => "Germany",
:title => "title of deal for German people") }
let(:deal_for_german_people2) { create(:deal_skips_validate,
:country => "Germany",
:title => "title 2 of deal for German people") }
before do
resize_window_to_mobile
create(:user_deal, user: user, deal: deal_for_german_people)
create(:user_deal, user: user, deal: deal_for_german_people2)
end
after do
resize_window_default
end
it "plus and minus icons behave correctly" do
visit root_path
# user sees on mobile the little "plus" icon by default
expect(page).to have_css('.card-detail-opener', visible: true)
end
end
此外,仍在调查这种怪异的原因,我发现如果我在测试开始时不使用 "let:" ,而是在 th 之前创建变量 @deals ...做块,它无需创建用户即可工作(但我想使用 rspec "let" 来 DRY 并应用 rspec best practices)
describe "HP card has the right content and behavior on small screens (1-column view)", :js => true do
let(:subject) { ApplicationController.new }
before do
resize_window_to_mobile
@deal_for_german_people = FactoryGirl.build( :deal,
:country => "Germany",
:title => "title of deal for German people").save(validate: false)
@deal_for_german_people2 = FactoryGirl.build( :deal,
:country => "Germany",
:title => "title 2 of deal for German people").save(validate: false)
end
after do
resize_window_default
end
it "plus and minus icons behave correctly" do
visit root_path
expect(page).to have_css('.card-detail-opener', visible: true)
end
型号
class Deal < ActiveRecord::Base
has_many :user_deals, dependent: :destroy
has_many :users, through: :user_deals
end
class User < ActiveRecord::Base
has_many :user_deals
has_many :deals, through: :user_deals
end
class UserDeal < ActiveRecord::Base
belongs_to :user, :foreign_key => 'user_id'
belongs_to :deal, :foreign_key => 'deal_id'
end
tableuser_deals
的结构
# Table name: user_deals
#
# id :integer not null, primary key
# user_id :integer
# deal_id :integer
# number_of_clicks :integer default(0)
# created_at :datetime
# updated_at :datetime
工厂用户
FactoryGirl.define do
factory :user do
sequence(:email) { |n| "person#{n}@example.com" }
password "vddfdf"
password_confirmation "vddfdf"
confirmed_at Time.now
confirmation_token nil
trait :superadmin do
role :superadmin
end
trait :with_deals do
after(:create) do |user|
create_list(:deal, 5, user: user)
end
end
end
end
工厂user_deal
FactoryGirl.define do
factory :user_deal do
association :user
association :deal
trait :few_clicks do
number_of_clicks 1
end
trait :many_clicks do
number_of_clicks 4
end
end
end
我的猜测是您期待两者
let(:deal_for_german_people) ...
let(:deal_for_german_people2) ...
在 it
块之前创建。但是,在您的第一个失败场景中,情况并非如此,因为您没有在 it
块的任何部分中 call/use 这些变量。您应该将 let
变量视为等待成为 运行 的代码。
我想你想要的是 let!
即刻 运行。
以下可能会起作用
context "As NON SIGNED-IN visitor" do
describe "HP card has the right content and behavior on small screens (1-column view)", :js => true do
...
let!(:deal_for_german_people) { create(:deal_skips_validate,
:country => "Germany",
:title => "title of deal for German people") }
let!(:deal_for_german_people2) { create(:deal_skips_validate,
:country => "Germany",
:title => "title 2 of deal for German people") }
...
end
end
我有一个奇怪的问题。我为 user/deal has_many/has_many 关系创建了一个工厂 user_deals,但似乎 rspec 现在迫使我断言一个用户,即使我不需要一个用户(确实是用户仅记录在我的数据库中,如果网络访问者登录,则在应用程序中需要)
此测试无效:
context "As NON SIGNED-IN visitor" do
describe "HP card has the right content and behavior on small screens (1-column view)", :js => true do
let(:subject) { ApplicationController.new }
let(:deal_for_german_people) { create(:deal_skips_validate,
:country => "Germany",
:title => "title of deal for German people") }
let(:deal_for_german_people2) { create(:deal_skips_validate,
:country => "Germany",
:title => "title 2 of deal for German people") }
before do
resize_window_to_mobile
end
after do
resize_window_default
end
it "plus and minus icons behave correctly" do
visit root_path
# user sees on mobile the little "plus" icon by default
expect(page).to have_css('.card-detail-opener', visible: true)
end
end
但如果我添加 create(:user) 并创建 "user_deals",测试通过。 但我在上下文中 "non signed in user",那么我为什么要创建一个用户和 user_deals 呢?
context "As NON SIGNED-IN visitor" do
describe "HP card has the right content and behavior on small screens (1-column view)", :js => true do
let(:subject) { ApplicationController.new }
let(:user) { create(:user,
user_country_name: 'Germany') }
let(:deal_for_german_people) { create(:deal_skips_validate,
:country => "Germany",
:title => "title of deal for German people") }
let(:deal_for_german_people2) { create(:deal_skips_validate,
:country => "Germany",
:title => "title 2 of deal for German people") }
before do
resize_window_to_mobile
create(:user_deal, user: user, deal: deal_for_german_people)
create(:user_deal, user: user, deal: deal_for_german_people2)
end
after do
resize_window_default
end
it "plus and minus icons behave correctly" do
visit root_path
# user sees on mobile the little "plus" icon by default
expect(page).to have_css('.card-detail-opener', visible: true)
end
end
此外,仍在调查这种怪异的原因,我发现如果我在测试开始时不使用 "let:" ,而是在 th 之前创建变量 @deals ...做块,它无需创建用户即可工作(但我想使用 rspec "let" 来 DRY 并应用 rspec best practices)
describe "HP card has the right content and behavior on small screens (1-column view)", :js => true do
let(:subject) { ApplicationController.new }
before do
resize_window_to_mobile
@deal_for_german_people = FactoryGirl.build( :deal,
:country => "Germany",
:title => "title of deal for German people").save(validate: false)
@deal_for_german_people2 = FactoryGirl.build( :deal,
:country => "Germany",
:title => "title 2 of deal for German people").save(validate: false)
end
after do
resize_window_default
end
it "plus and minus icons behave correctly" do
visit root_path
expect(page).to have_css('.card-detail-opener', visible: true)
end
型号
class Deal < ActiveRecord::Base
has_many :user_deals, dependent: :destroy
has_many :users, through: :user_deals
end
class User < ActiveRecord::Base
has_many :user_deals
has_many :deals, through: :user_deals
end
class UserDeal < ActiveRecord::Base
belongs_to :user, :foreign_key => 'user_id'
belongs_to :deal, :foreign_key => 'deal_id'
end
tableuser_deals
的结构# Table name: user_deals
#
# id :integer not null, primary key
# user_id :integer
# deal_id :integer
# number_of_clicks :integer default(0)
# created_at :datetime
# updated_at :datetime
工厂用户
FactoryGirl.define do
factory :user do
sequence(:email) { |n| "person#{n}@example.com" }
password "vddfdf"
password_confirmation "vddfdf"
confirmed_at Time.now
confirmation_token nil
trait :superadmin do
role :superadmin
end
trait :with_deals do
after(:create) do |user|
create_list(:deal, 5, user: user)
end
end
end
end
工厂user_deal
FactoryGirl.define do
factory :user_deal do
association :user
association :deal
trait :few_clicks do
number_of_clicks 1
end
trait :many_clicks do
number_of_clicks 4
end
end
end
我的猜测是您期待两者
let(:deal_for_german_people) ...
let(:deal_for_german_people2) ...
在 it
块之前创建。但是,在您的第一个失败场景中,情况并非如此,因为您没有在 it
块的任何部分中 call/use 这些变量。您应该将 let
变量视为等待成为 运行 的代码。
我想你想要的是 let!
即刻 运行。
以下可能会起作用
context "As NON SIGNED-IN visitor" do
describe "HP card has the right content and behavior on small screens (1-column view)", :js => true do
...
let!(:deal_for_german_people) { create(:deal_skips_validate,
:country => "Germany",
:title => "title of deal for German people") }
let!(:deal_for_german_people2) { create(:deal_skips_validate,
:country => "Germany",
:title => "title 2 of deal for German people") }
...
end
end