我想写一个rspec测试来验证一个类方法,它通过类名调用包含的模块方法。当我使用Module名称调用模块方法时,它可以正常工作,但在按类名调用时会抛出NoMethodError。
module Test
def self.module_mtd
p "test"
end
end
class Burger
include Test
attr_reader :options
def initialize(options={})
@options = options
end
def apply_ketchup
@ketchup = @options[:ketchup]
end
def has_ketchup_on_it?
Burger.module_mtd # Throws NoMethodError
Test.module_mtd #Works fine as expected
@ketchup
end
end
describe Burger do
describe "#apply_ketchup" do
subject { burger }
before { burger.apply_ketchup }
context "with ketchup" do
let(:burger) { Burger.new(:ketchup => true) }
it { should have_ketchup_on_it }
end
context "without ketchup" do
let(:burger) { Burger.new(:ketchup => false) }
it { should_not have_ketchup_on_it }
end
end
end
答案 0 :(得分:1)
问题不在于测试本身,而在于你对类方法如何在Ruby中工作的理解。
module Test
def self.module_mtd
p "test"
end
end
声明属于Test
的方法。与模块实例方法不同,当您包含模块时,不会将其添加到类中。
要从模块声明一个类方法,您需要使用模块mixins模式来扩展单例类:
module Test
# this is called when you include the module
def self.included(base)
# this adds the class methods to the class
base.extend ClassMethods
end
module ClassMethods
def foo
puts "hello world"
end
end
end
module ClassMethods
将foo
声明为实例方法这一事实看起来有点令人困惑,直到您意识到要扩展的单例类是" Class"的实例。
请参阅: