我有一个扩展 ActiveSupport::Concern 的模块。这是included
块:
included do
after_save :save_tags
has_many :taggings, :as => :taggable
has_many :tags, :through => :taggings
end
我怎样才能消除这些电话?我尝试了几种方法,但是当我尝试单独测试模块时,Ruby 抱怨说这些方法不存在。
谢谢!
我有一个扩展 ActiveSupport::Concern 的模块。这是included
块:
included do
after_save :save_tags
has_many :taggings, :as => :taggable
has_many :tags, :through => :taggings
end
我怎样才能消除这些电话?我尝试了几种方法,但是当我尝试单独测试模块时,Ruby 抱怨说这些方法不存在。
谢谢!
我认为您有几个选择,具体取决于您要测试的内容。
如果您只想测试模块是否实际设置了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 关联的行为,您可以创建另一个 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
在您的测试开始之前,您需要确保首先使用 ActiveSupport::Concern 的原始定义加载文件,然后加载您的扩展。确保加载正确的文件,因为 rails 自动加载机制会发现您的扩展有利于原始文件。