工厂女孩协会的问题和使用let:

时间:2016-05-10 08:39:43

标签: ruby-on-rails ruby-on-rails-4 rspec factory-bot

我有一个奇怪的问题。我为一个用户/交易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”,则测试通过。但我在上下文中“未登录用户”,那么我为什么要创建一个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:”,而是在...之前创建变量@deals ...它可以在不创建用户的情况下工作(但是我想使用rspec“let”来干燥并应用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

表user_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

1 个答案:

答案 0 :(得分:1)

我的猜测是你期待两个

let(:deal_for_german_people) ...
let(:deal_for_german_people2) ...

it块之前创建。但是,在您的第一个失败的情况下,情况并非如此,因为您没有在it块的任何部分调用/使用这些变量。您应该将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