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的行为。