gpt4 book ai didi

ruby-on-rails - 通过使用 RSpec 和 Factory Girl 进行模型验证的 has_many TDD

转载 作者:行者123 更新时间:2023-12-04 06:29:11 25 4
gpt4 key购买 nike

考虑以下:

ScheduledSession ------> Applicant <------ ApplicantSignup

注意事项:
  • ScheduledSession 会一直存在于系统中;将此视为一门类(class)或类(class)。
  • 这里的目的是在 signups_controller#create 期间根据 ScheduledSession 上的属性验证申请人注册模型。

  • 协会
    class ScheduledSession < ActiveRecord::Base
    has_many :applicants, :dependent => :destroy
    has_many :applicant_signups, :through => :applicants
    #...
    end

    class ApplicantSignup < ActiveRecord::Base
    has_many :applicants, :dependent => :destroy
    has_many :scheduled_sessions, :through => :applicants
    #...
    end

    class Applicant < ActiveRecord::Base
    belongs_to :scheduled_session
    belongs_to :applicant_signup

    # TODO: enforce validations for presence
    # and uniqueness constraints etc.
    #...
    end

    注册 Controller

    资源是 RESTful,即 #create Action 将有一个类似于 /scheduled_sessions/:id/signups/new 的路径
    def new
    @session = ScheduledSession.find(params[:scheduled_session_id])
    @signup = @session.signups.new
    end

    def create
    @session = ScheduledSession.find(params[:scheduled_session_id])
    @session.duration = (@session.end.to_time - @session.start.to_time).to_i
    @signup = ApplicantSignup.new(params[:signup].merge(:sessions => [@session]))

    if @signup.save
    # ...
    else
    render :new
    end
    end

    您会注意到我在 @session.duration 上方设置了一个虚拟属性。防止 Session 被认为无效。如果您愿意,真正的“魔法”发生在 @signup = ApplicantSignup.new(params[:signup].merge(:sessions => [@session]))这现在意味着在模型中我可以从 self.scheduled_sessions 中选择并访问此申请者注册所针对的 ScheduledSession,即使此时此刻,联接表中不存在记录。

    例如模型验证看起来像
    def ensure_session_is_upcoming
    errors[:base] << "Cannot signup for an expired session" unless self.scheduled_sessions.select { |r| r.upcoming? }.size > 0
    end

    def ensure_published_session
    errors[:base] << "Cannot signup for an unpublished session" if self.scheduled_sessions.any? { |r| r.published == false }
    end

    def validate_allowed_age
    # raise StandardError, self.scheduled_sessions.inspect
    if self.scheduled_sessions.select { |r| r.allowed_age == "adults" }.size > 0
    errors.add(:dob_year) unless (dob_year.to_i >= Time.now.strftime('%Y').to_i-85 && dob_year.to_i <= Time.now.strftime('%Y').to_i-18)
    # elsif ... == "children"
    end
    end

    以上在 development 中运行良好并且验证按预期工作 - 但是如何使用 Factory Girl 进行测试?我想要单元测试来保证我已经实现的业务逻辑——当然,这是在事实之后,但仍然是关于 TDD 的一种方式。

    你会注意到我已经注释掉了 raise StandardError, self.scheduled_sessions.inspect在上面的最后一次验证中 - 这将返回 []self.scheduled_sessions这表明我的工厂设置不正确。

    许多尝试之一 =)
    it "should be able to signup to a session" do
    scheduled_session = Factory.build(:scheduled_session)
    applicant_signup = Factory.build(:applicant_signup)
    applicant = Factory.create(:applicant, :scheduled_session => scheduled_session, :applicant_signup => applicant_signup)
    applicant_signup.should be_valid
    end

    it "should be able to signup to a session for adults if between 18 and 85 years" do
    scheduled_session = Factory.build(:scheduled_session)
    applicant_signup = Factory.build(:applicant_signup)
    applicant_signup.dob_year = 1983 # 28-years old
    applicant = Factory.create(:applicant, :scheduled_session => scheduled_session, :applicant_signup => applicant_signup)
    applicant_signup.should have(0).error_on(:dob_year)
    end

    第一个通过了,但老实说,我不相信它正确地验证了申请人_注册模型;事实 self.scheduled_sessions正在返回 []只是意味着以上是不对的。

    我很可能正在尝试测试 Factory Girl 范围之外的东西,或者有没有更好的方法来解决这个问题?感谢所有的评论、建议和 build 性的批评!

    更新:
  • 不知道这叫什么,但这是至少对 how it's implemented at the controller level 采取的方法
  • 我至少需要考虑在关联方面忽略工厂女孩并尝试返回scheduled_session通过 mock scheduled_sessionsapplicant_signup模型。

  • 工厂
    FactoryGirl.define do  
    factory :signup do
    title "Mr."
    first_name "Franklin"
    middle_name "Delano"
    last_name "Roosevelt"
    sequence(:civil_id) {"#{'%012d' % Random.new.rand((10 ** 11)...(10 ** 12))}"}
    sequence(:email) {|n| "person#{n}@#{(1..100).to_a.sample}example.com" }
    gender "male"
    dob_year "1980"
    sequence(:phone_number) { |n| "#{'%08d' % Random.new.rand((10 ** 7)...(10 ** 8))}" }
    address_line1 "some road"
    address_line2 "near a pile of sand"
    occupation "code ninja"
    work_place "Dharma Initiative"
    end

    factory :session do
    title "Example title"
    start DateTime.civil_from_format(:local,2011,12,27,16,0,0)
    duration 90
    language "Arabic"
    slides_language "Arabic & English"
    venue "Main Room"
    audience "Diabetic Adults"
    allowed_age "adults"
    allowed_gender "both"
    capacity 15
    published true
    after_build do |session|
    # signups will be assigned manually on a per test basis
    # session.signups << FactoryGirl.build(:signup, :session => session)
    end
    end

    factory :applicant do
    association :session
    association :signup
    end

    #...
    end

    最佳答案

    我之前的假设是正确的,只是有一些小的变化:

    I need to consider ignoring Factory Girl for the association aspect at least and attempt to return the scheduled_session by stubbing scheduled_sessions on the applicant_signup model.



    让我的测试非常简单:
    it "should be able to applicant_signup to a scheduled_session" do
    scheduled_session = Factory(:scheduled_session)
    applicant_signup = Factory.build(:applicant_signup)
    applicant_signup.stub!(:scheduled_sessions).and_return{[scheduled_session]}
    applicant_signup.should be_valid
    end

    it "should be able to applicant_signup to a scheduled_session for adults if between 18 and 85 years" do
    scheduled_session = Factory(:scheduled_session)
    applicant_signup = Factory.build(:applicant_signup)
    applicant_signup.dob_year = 1983 # 28-years old
    applicant_signup.stub!(:scheduled_sessions).and_return{[scheduled_session]}
    applicant_signup.should have(0).error_on(:dob_year)
    applicant_signup.should be_valid
    end

    这个测试特别需要类似的方法:
    it "should not be able to applicant_signup if the scheduled_session capacity has been met" do
    scheduled_session = Factory.build(:scheduled_session, :capacity => 3)
    scheduled_session.stub_chain(:applicant_signups, :count).and_return(3)
    applicant_signup = Factory.build(:applicant_signup)
    applicant_signup.stub!(:scheduled_sessions).and_return{[scheduled_session]}
    applicant_signup.should_not be_valid
    end

    ...和成功 - 忽略测试持续时间为 spork导致虚假报道。
    Finished in 2253.64 seconds
    32 examples, 0 failures, 3 pending
    Done.

    关于ruby-on-rails - 通过使用 RSpec 和 Factory Girl 进行模型验证的 has_many TDD,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8100440/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com