测试动态创建的方法

时间:2012-03-12 21:31:31

标签: ruby-on-rails unit-testing rspec

在我的模型中,我基于数据库记录动态创建一些方法:

class Job < ActiveRecord::Base
  belongs_to :job_status

  # Adds #requisition?, #open?, #paused?, #closed?
  class_eval do    
    JobStatus.all.each do |status|
      unless method_defined? "#{status.name.downcase}?"
        define_method("#{status.name.downcase}?") do 
          job_status_id == status.id
        end
      end
    end
  end
end

class JobStatus < ActiveRecord::Base
  has_many :jobs
end

job_statuses表包含一些种子数据,因此不会经常更改,但是如果我需要添加新状态,我不必添加更多代码来获取布尔方法新的状态。

但是,我不确定如何测试这些方法,因为当rspec启动时job_statuses表显然是空的,并且在创建JobStatus对象时,Job被初始化,但由于还没有对象存在,它不会创建任何方法,并且我的测试失败,因为这些方法不存在。

请注意,我正在使用sppec&amp;保护,并使用数据库清理器与截断策略(根据Railscast #257,因为我使用Selenium),所以这可能使问题复杂化。

2 个答案:

答案 0 :(得分:0)

我想出的解决方案是将运行时方法的创建抽象到库文件中,然后在我的测试文件中,在每次测试之前删除并重新声明我的类,然后重新加载实际的类(和蓝图)。套房结束:

describe AssociationPredicate do
  before(:all) do
    ["Continuous", "Standard"].each { |type| JobType.create!(:job_type => type) }
    ["Requisition", "Open", "Paused", "Closed"].each { |status| JobStatus.create!(:job_status => status) }
  end

  after(:all) do
    DatabaseCleaner.clean_with :truncation, :only => %w( job_types job_statuses )

    # Reload Job model to remove changes
    Object.send(:remove_const, 'Job')
    load 'job.rb'
    load 'support/blueprints.rb'
  end

  before(:each) do
    Object.send(:remove_const, 'Job')

    # Redefine Job model for testing purposes
    class Job < ActiveRecord::Base
      belongs_to  :job_type
      belongs_to  :job_status

      has_many    :job_applications
    end
  end

  it "should add methods when included" do
    Job.send(:association_predicate, :job_type)
    job.should respond_to(:continuous?)
    job.should respond_to(:standard?)
  end
end

这样,我为每个测试创建一个基本类,必要时添加运行时方法,并在完成后返回实际的类。

答案 1 :(得分:0)

尝试使用 enumerize gem。这会使您的状态字段像枚举器一样构建“#{status.name.downcase}?”为您的模型。 This gem 附带了自己的rspec-matchers,使您的单元测试变得最简单。