下面是一些簡單的代碼,對於指定的每個參數,都會添加以該參數命名的特定get/set方法。如果你寫attr_option :foo, :bar
,然後你會看到Config
#foo/foo=
和#bar/bar=
實例方法:如何編寫RSpec測試來單元測試這個有趣的元編程代碼?
module Configurator
class Config
def initialize()
@options = {}
end
def self.attr_option(*args)
args.each do |a|
if not self.method_defined?(a)
define_method "#{a}" do
@options[:"#{a}"] ||= {}
end
define_method "#{a}=" do |v|
@options[:"#{a}"] = v
end
else
throw Exception.new("already have attr_option for #{a}")
end
end
end
end
end
到目前爲止,一切都很好。我想寫一些RSpec測試來驗證這段代碼實際上正在做它應該做的事情。但是有一個問題!如果我在其中一種測試方法中調用attr_option :foo
,則現在在Config中永遠定義該方法。所以,因爲foo
已經定義的後續測試將當它不應該失敗:
it "should support a specified option" do
c = Configurator::Config
c.attr_option :foo
# ...
end
it "should support multiple options" do
c = Configurator::Config
c.attr_option :foo, :bar, :baz # Error! :foo already defined
# by a previous test.
# ...
end
有沒有一種方法,我可以給每個測試Config
類的匿名「克隆」,這是獨立於其他的?
+1對於堅實的建議和新穎的方法;我不會想到創建匿名類,並且正在考慮像創建類的匿名模塊然後銷燬它。這顯然是更好的解決方案。 – 2010-05-23 15:37:25