Я думаю, у вас есть пара вариантов, в зависимости от того, что вы хотите проверить.
Если вы просто хотите проверить, что модуль действительно устанавливает 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
Youвозможно, вы можете довольно легко протестировать метод save_tags
без дальнейшей насмешки, но если вы хотите протестировать поведение, которое зависит от настраиваемых ассоциаций has_many, вы можете создать другой класс Dummy с заглушкой has_many и after_save, но с аксессорами для ассоциаций:
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