开发者

How do you test a module that extends ActiveSupport::Concern?

I have a module that extends ActiveSupport::Concern. Here is the included block:

included do
  after_save :save_tags

  has_many :taggings, :as =&g开发者_StackOverflowt; :taggable
  has_many :tags, :through => :taggings
end

How can I stub out these calls? I have tried a few ways, but Ruby complains that these methods don't exist when I try and test the module in isolation.

Thanks!


I think you have a couple options, depending on what it is that you want to test.

If you just want to test that the module actually sets up the has_many associations and after_save call back, then you could set up a simple rspec expectation:

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

You probably can test the save_tags method pretty easily without further mocking, but if you want to test behavior that depends on the has_many associations being setup you might create another Dummy class with has_many and after_save stubbed out, but with accessors for the associations:

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

We can clean that (somewhat brittle test class) up with a bit of meta programming, though it's up to your judgement on whether this makes the test too difficult to understand.

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


Before your test starts, you need to make sure you first load the file with the original definition of ActiveSupport::Concern and after that load you have to load your extention. Be sure to load the correct files as the rails autoloading mechanism will find your extention in favor of the original.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜