如何测试扩展ActiveSupport :: Concern的模块?

时间:2011-05-31 18:09:58

标签: ruby-on-rails ruby module rspec activesupport

我有一个扩展ActiveSupport :: Concern的模块。这是included块:

included do
  after_save :save_tags

  has_many :taggings, :as => :taggable
  has_many :tags, :through => :taggings
end

如何固定这些电话?我尝试过几种方法,但是当我尝试单独测试模块时,Ruby抱怨这些方法不存在。

谢谢!

2 个答案:

答案 0 :(得分:3)

我认为你有几个选择,具体取决于你想测试的是什么。

如果您只想测试模块实际设置has_many关联和after_save回调,那么您可以设置一个简单的rspec期望:

class Dummy
end

describe Taggable do
  it "should setup active record associations when included into models" do
    Dummy.should_receive(:has_many).twice
    Dummy.should_receive(:after_save).with(:save_tags)
    Dummy.send(:include, Taggable) # send is necessary because it's a private method
  end
end

您可以非常轻松地测试save_tags方法而无需进一步模拟,但如果您想测试依赖于正在设置的has_many关联的行为,您可能会创建另一个带有has_many和after_save的Dummy类,但是协会的访问者:

class Dummy
  attr_accessor :taggings, :tags

  # stub out these two
  def self.has_many
  end

  def self.after_save
  end

  def initialize
    @taggings = []
    @tags = []
  end

  include Taggable
end

describe Taggable do
  it "should provide a formatted list of tags, or something" do
     d = Dummy.new
     d.tags = [double('tag')]
     d.formatted_tags.size.should == 1
  end
end

我们可以通过一些元编程来清理(稍微脆弱的测试类),但这取决于你是否会让测试难以理解。

class Dummy
  def self.has_many(plural_object_name, options={})
    instance_var_sym = "@#{plural_object_name}".to_sym

    # Create the attr_reader, setting the instance var if it doesn't exist already
    define_method(plural_object_name) do
      instance_variable_get(instance_var_sym) ||
          instance_variable_set(instance_var_sym, [])
    end

    # Create the attr_writer
    define_method("#{plural_object_name}=") do |val|
      instance_variable_set(instance_var_sym, val)
    end
  end

  include Taskable
end

答案 1 :(得分:0)

在测试开始之前,您需要确保首先使用ActiveSupport :: Concern的原始定义加载文件,然后在加载后必须加载扩展。请务必加载正确的文件,因为rails自动加载机制会找到您的扩展名,而不是原始文件。