【问题标题】:Rspec: Factory Girl & Complex AssociationsRspec:工厂女孩和复杂协会
【发布时间】:2015-06-16 19:42:19
【问题描述】:

我正在尝试测试一个帮助方法,该方法将返回 Subscribers 的数量 Campaign 是针对的。作为 TDD 的新手,我很难思考如何编写这个,因为关联非常复杂。 Campaign“目标”通过订阅者是否在目标plan 上并选择加入目标program

如何让我的 Factory Girl 对象相互关联以继续编写规范?尽管看起来很简单,但我无法让他们合作。

这里是模型关联..

models/campaign.rb

class Campaign < ActiveRecord::Base
    belongs_to :program
    belongs_to :plan
end

models/subscriber.rb

class Subscriber < ActiveRecord::Base
    has_many :plans, through: :plannables
end

models/plan.rb

class Plan < ActiveRecord::Base
    has_many :subscribers, through: :plannables
    has_many :plannables
    has_many :campaigns

    validates :name, presence: true,
                uniqueness: true
end

models/program.rb

class Program < ActiveRecord::Base
    has_many :campaigns

    validates :name, presence: true,
                     uniqueness: true
end

models/plannable.rb

class Plannable < ActiveRecord::Base
    belongs_to :plans
    belongs_to :subscribers
end

这里是工厂..

spec/factories/campaign.rb

FactoryGirl.define do

    factory :campaign do |x|
        x.sequence(:name) { |y| "201#{y} Example" }
        x.sequence(:comment) { |y| "The #{y} example" }
        channels ["Folder", "Fax"]
    end

    factory :program do
        name "Sims"
        comment "the sims program"
    end

    factory :plan do
        name "PDX"
    end
end

spec/factories/subscribers.rb

FactoryGirl.define do
    sequence(:first_name) { |y| "Sam #{y}" }
    sequence(:last_name) { |y| "Sm#{y}th" }
    sequence(:email) { |y| "email#{y}@sub.com".downcase }

    factory :subscriber do
        first_name
        last_name
        email
        password "secret123"
        home_duid { SecureRandom.uuid }
        admin false
        sims true  #opt-in status
        cups false  #opt-in status
        tire false #opt-in status
    end


end

...和我的规格..

spec/helpers/application_helper_spec.rb

require "rails_helper"

RSpec.describe ApplicationHelper, :type => :helper do
    before :all do
        @program = create(:program)
        @subscriber = create(:subscriber, star: true)
        @campaign = create(:campaign, plan_id: @plan, program_id: @program)
        @plan = Plan.new(name: "STX)", subscriber_id: @subscriber)
    end

    describe "Campaign subscriber listing" do
        it "finds subscribers that opt-in to affiliated program" do
          expect(@campaign.plan_id).to eq @plan
        end
    end
end

作为一个初学者,为了简单地测试我在上面通过对象 ID 创建的关联,我添加了第一个规范 - 但我什至无法让它通过..知道我可能缺少什么吗?

失败:

 1) ApplicationHelper Campaign subscriber listing finds subscribers that opt-in to affiliated program
     Failure/Error: expect(campaign.plan).to eq plan

       expected: #<Plan id: 3, name: "PDX", created_at: "2015-06-16 20:51:18", updated_at: "2015-06-16 20:51:18", plan_id: nil>
            got: nil

       (compared using ==)
     # ./spec/helpers/application_helper_spec.rb:19:in `block (3 levels) in <top (required)>'

更新

我尝试在我的campaign factory 中使用 Factory Girl association..

factory :campaign do |x|
    x.sequence(:name) { |y| "201#{y} Example" }
    x.sequence(:comment) { |y| "The #{y} example" }
    channels ["Folder", "Fax"]
    association plan
end

但是收到一个令人困惑的错误...

* plan - Validation failed: Name has already been taken

我尝试将名称更改为随机名称,但仍然出现此错误。

【问题讨论】:

  • 使用@instance_variables很重。更喜欢使用let(:program) { create(:program) }subject(:program) { create(:program) }let 是延迟加载的。
  • @davidwessman - 谢谢!我会做出这些改变。
  • 您认为您可以详细说明您的其他问题吗?你想在测试中做什么?
  • @davidwessman - 在活动index 视图中,我想显示每个活动有多少subscribers。当我使用 TDD 时,我需要编写一个测试,将 Campaign 对象的关联(计划和/或程序)与有效的 Subscriber 匹配。我遇到的问题是将 Factory Girl 对象关联起来,以便 @campaign 属于STX 计划。

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


【解决方案1】:
campaign = create(:campaign, plan_id: @plan, program_id: @program)

尝试更改为:

subject(:campaign) { create(:campaign, plan: plan, program: program) }

只要你是结果,也可以用 id 来做。

我在这里打错了:

subject(:campaign) { create(:campaign, plan_id: plan_id, program_id: program_id) }

应该是:

subject(:campaign) { create(:campaign, plan_id: plan.id, program:id: program.id) }

【讨论】:

    【解决方案2】:

    您还没有向 展示您的测试如何失败,这使得提供帮助有点困难,但是您正在将 plan_id@plan 对象进行比较。尝试将@campaign.plan_id 更改为@campaign.plan

    【讨论】:

    • 嘿安迪,我做了你提出的改变并在上面发布了失败消息。这与我使用@campaign.plan_id 时收到的几乎相同。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多