假设我有以下模块:
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
然后是以下最小的:
require_relative 'sillydemo'
require "minitest/spec"
require "minitest/autorun"
describe "Ape" do
before do
@ape = Ape.new
@screech = "YEEEEEEE"
end
it "screeches" do
@ape.screech(@screech)
must_send [@ape, :process, @screech]
must_send [@ape, :super, @screech]
end
end
这出错了:
NoMethodError: undefined method `super' for #<SillyDemo::Ape:0x007feeb10943c0>
(eval):4:in `must_send'
我也尝试过:
must_send [@ape, :"SillyDemo::Monkey.screech", @screech]
出错的地方:
NoMethodError: undefined method `SillyDemo::Ape.run' for #<SillyDemo::Ape:0x007fc5a1874e20>
(eval):4:in `must_send'
我的问题是,如何使用minitest来测试对super的调用?
答案 0 :(得分:0)
在Ruby super
中是关键字,而不是方法。此外,must_send
期望不会验证方法是否被调用,它只是验证方法的返回值是否真实。
http://www.ruby-doc.org/stdlib-2.0.0/libdoc/minitest/rdoc/MiniTest/Expectations.html#method-i-must_send http://www.ruby-doc.org/stdlib-2.0.0/libdoc/minitest/rdoc/MiniTest/Assertions.html#method-i-assert_send
模拟通常用于验证方法是否被调用。但是,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
非常难看,对吗?这是设计的。有点像句法醋。原因是这种模拟的使用并不是很有用。它正在检查代码的实现。您希望能够在不改变行为的情况下重构代码并让测试继续通过。但是,当实现更改时,此测试很可能会失败。为了阻止人们犯这种错误,Minitest的作者决定让这种检查变得困难。