对ruby,rails和单元测试很新,所以欢迎任何其他反馈!
我正在为一个名为#assign_campaign的基于ActiveRecord的模型(联系人)编写一个rspec单元测试。 ContactCampaign是一个将联系人映射到广告系列的关联。这里的想法是,当广告系列被分配时,该联系人的所有其他广告系列都会停用,并且已分配的广告系列也会被激活。
测试失败,因为它声称已分配的广告系列的状态为零而非“有效”(或“无效”)。
似乎归结为“campaign_id”属性上的“where”匹配似乎不会返回相同的对象,就像我遍历contact_campaigns并且也匹配campaign_id一样。
E.g。
contact.contact_campaigns.where(campaign_id: campaign_to_be_assigned.id).first.inspect
抓住我:
< ContactCampaign id:6,contact_id:1,campaign_id:1,status:nil,created_at:“2013-09-11 23:40:07”,updated_at:“2013-09-11 23:40:07 “,current_position:1>
使用object_id:70199917191760
虽然
contact.contact_campaigns.each do |x|
if x.campaign_id == campaign_to_be_assigned.id
puts x.inspect
end
end
抓住我:
< ContactCampaign id:6,contact_id:1,campaign_id:1,status:“active”,created_at:“2013-09-11 23:40:07”,updated_at:“2013-09-11 23:40 :08“,current_position:1>
使用object_id:70199940110940
这里发生了什么?这是一个ActiveRecord失败,FactoryGirl失败或简单的Ruby失败? ; p
如果我从:
重写assign_campaigncurrent_contact_campaign = contact_campaigns.where(campaign_id: campaign_id).first
current_contact_campaign.activate
current_contact_campaign.set_current_position(starting_position) unless
starting_position == 0
致:
contact_campaigns.each do |x|
if x.campaign_id == campaign_id
x.activate
x.set_current_position(starting_position) unless
starting_position == 0
end
end
然后一切都很开心,但我想知道发生了什么。
Rspec测试:
it "assign_campaign assigns a campaign, creates a new campaign task,
note and deactivates other contact campaigns, one was active previously" do
# not checking the note portion right now
contact = FactoryGirl.create(:contact, user: user)
campaign_to_be_assigned = FactoryGirl.create(:campaign)
campaign_to_be_assigned.messages << FactoryGirl.create(:message)
5.times do |i|
contact.campaigns << FactoryGirl.create(:campaign)
end
contact.deactivate_contact_campaigns
# Randomly activates one of the generated campaigns
contact.contact_campaigns[rand(4)].activate
contact.assign_campaign(campaign_to_be_assigned.id)
contact.contact_campaigns.each do |x|
if x.campaign_id == campaign_to_be_assigned.id
x.status.should == 'active'
else
x.status.should == 'inactive'
end
end
end
正在测试的方法:
def assign_campaign(campaign_id=nil, starting_position = 0, opts = {})
if email_is_valid || campaign_id == nil
if !campaign_id.blank?
campaign = Campaign.find(campaign_id)
deactivate_contact_campaigns
campaigns << campaign if !campaigns.include? campaign
current_contact_campaign = contact_campaigns.where(campaign_id: campaign_id).first
current_contact_campaign.activate
current_contact_campaign.set_current_position(starting_position) unless
starting_position == 0
notes.create(user_id: user.id, body: "Assigned #{name} to " +
campaign.description, group: "system",
created_at: (opts[:assign_time] ? opts[:assign_time] : Time.now))
create_new_campaign_task(opts[:user_id],
(starting_position == 0 ? 0 : (starting_position - 1)))
return true
else
notes.create(user_id: user.id,
body: "Unassigned #{name} from campaign", group: "system",
created_at: (opts[:assign_time] ? opts[:assign_time] : Time.now)) if
contact_campaigns.where(status: 'active').size > 0
deactivate_contact_campaigns
end
else
return false
end
end
测试失败消息
Failures:
1) Contact assign_campaign assigns a campaign, creates a new campaign task,
note and deactivates other contact campaigns, one was active previously
Failure/Error: x.status.should == 'active'
expected: "active"
got: nil (using ==)
# ./spec/models/contact_spec.rb:78:in `block (3 levels) in <top (required)>'
# ./spec/models/contact_spec.rb:76:in `block (2 levels) in <top (required)>'
FactoryGirl工厂
广告活动
FactoryGirl.define do
factory :campaign do |campaign|
sequence(:description) { |n| "description#{n}"}
end
end
联系人
require 'faker'
FactoryGirl.define do
factory :contact do |contact|
fake_email = Faker::Internet.email
association :organization, factory: :organization
sequence(:email) { |n| "#{n}#{fake_email}" }
end
end
消息
FactoryGirl.define do
factory :message do |message|
message.description { "Considering buying your first home?" }
message.position { 0 }
message.interval { 0 }
message.email_subject { "Considering buying your first home?" }
message.email_body { "I have several valuable resources if you are considering buying your first home. I'm happy to discuss the process of buying a home in simple, easy-to-understand terms, or I can help point you in the right direction to get the best loan for a home purchase.\n\nIf you're just curious what you can get for your money, I'm happy to show you a few properties in your area so you can see what is available. Give me a call today anytime. I look forward to hearing from you." }
end
end
答案 0 :(得分:1)
关于您关于object_ids的第一个问题:
object_id是Ruby中分配给实际实例的内部引用ID。没有两个实例可以具有相同的object_id。这与在Rails中调用.id不同,后者应返回数据存储区中记录的id。
为什么您的测试可能失败: 你打电话的那一刻:
contact.contact_campaigns[rand(4)].activate
Rails命中您的数据存储区并在本地缓存该集合。然后你“激活”项目rand(4),这显然是你的意图。
然后你称之为:
contact.assign_campaign(campaign_to_be_assigned.id)
应该已经停用了之前活动的rand(4)。但是,在contact.contact_campaigns的内存中的 NOT 数据存储区中。所以请记住contact.contact_campaigns仍在内存中并认为rand(4)已激活。所以在你这样做之前:
contact.contact_campaigns.each do...
您应该重新加载该集合:
contact.contact_campaigns.reload
希望这有帮助!