Ruby 用户必须使用在minitest中调用super的方法发送
假设我有以下模块:Ruby 用户必须使用在minitest中调用super的方法发送,ruby,unit-testing,inheritance,ruby-1.9,minitest,Ruby,Unit Testing,Inheritance,Ruby 1.9,Minitest,假设我有以下模块: module SillyDemo class Monkey def screech(sound) sound end end class Ape < Monkey def process(sound) sound end def screech(sound) process(sound) super sound end
module SillyDemo
class Monkey
def screech(sound)
sound
end
end
class Ape < Monkey
def process(sound)
sound
end
def screech(sound)
process(sound)
super
sound
end
end
end
此错误与以下内容有关:
NoMethodError: undefined method `super' for #<SillyDemo::Ape:0x007feeb10943c0>
(eval):4:in `must_send'
NoMethodError: undefined method `SillyDemo::Ape.run' for #<SillyDemo::Ape:0x007fc5a1874e20>
(eval):4:in `must_send'
哪些错误与以下内容有关:
NoMethodError: undefined method `super' for #<SillyDemo::Ape:0x007feeb10943c0>
(eval):4:in `must_send'
NoMethodError: undefined method `SillyDemo::Ape.run' for #<SillyDemo::Ape:0x007fc5a1874e20>
(eval):4:in `must_send'
NoMethodError:for的未定义方法'SillyDemo::Ape.run'#
(评估):4:在“必须发送”中
我的问题是,如何使用minitest来测试对super的调用?在Ruby中,super是一个关键字,而不是一个方法。另外,
must\u send
期望值并没有验证方法是否被调用,它只是验证方法的返回值是否真实
mock通常用于验证是否调用了方法。然而,Minitest::Mock在设计上不允许很容易地进行这种类型的检查。下面是如何做到这一点
it "screeches" do
# 1) Create mock
sound_mock = Minitest::Mock.new
sound_mock.expect :process, true, [String]
# 2) Place mock
@ape.instance_exec(sound_mock) do |sound_mock|
@mock = sound_mock
def process sound
@mock.process sound
end
end
# 3) Verify mock was called
@ape.screech(@screech)
sound_mock.verify
end
很难看,对吧?这是故意的。有点像醋。原因是mock的这种使用并不是很有用。它正在检查代码的实现。您希望能够在不改变行为的情况下重构代码,并让测试继续通过。但是,当实现发生更改时,此测试很可能会失败。为了防止人们犯这种错误,Minitest的作者决定让这种检查变得困难
其他模拟库(如or)使这种类型的检查更容易。但这仍然只测试发送的进程,我在初始代码示例中使用了该进程,而没有验证被覆盖的超类方法是否由super调用。这就是实现。使用mock来验证实现是个坏主意™ 依我拙见改为测试API的行为。