【问题标题】:Minitest - calling a mocked instance method from within another instance methodMinitest - 从另一个实例方法中调用模拟实例方法
【发布时间】:2018-07-01 07:49:15
【问题描述】:

我在Minitest::Mock 中遇到了一些奇怪的行为,无法弄清楚背后的原因。

假设我有一个类 A,它有一个方法 b,它调用方法 c:

class A

  def b
    c
  end

  def c
    1
  end

end

我想模拟 c 方法返回 2 而不是 1:

require 'minitest/autorun'

a = Minitest::Mock.new(A.new)
a.expect(:c, 2)

但由于某种原因b 仍然返回 1:

> a.b
=> 1 

显然直接调用c 会起作用:

> a.c
=> 2
> a.c
MockExpectationError: No more expects available for :c: []

为什么在实例中调用 c 时没有调用它的期望?

【问题讨论】:

    标签: ruby-on-rails ruby mocking minitest


    【解决方案1】:

    这就是Minitest::Mock 的工作原理;模拟对象是A 的“真实”实例的包装器,并且定义的期望会在方法调用到达该实例之前拦截它。 (其他方法,如 b,没有定义预期,在不受影响的情况下转发 - 尽管它们仍然通过模拟。)

    当实例在内部进行方法调用时,它们直接转到self,而不是通过模拟包装器返回,因此它们被正常调度,没有被拦截的机会。


    【讨论】:

    • 感谢@matthewd 的回复!那么有没有办法让我以某种方式存根c?假设我正在尝试测试调用 #save 的 Rails 模型的方法。出于性能原因,我想存根 #save。
    • 你可能想要stub; mock 的重点是期望,而 stub 用于将行为强制到被测系统中。
    • 但我确实希望有所期待。我测试的方法可能有一些逻辑,它调用或不调用#save 方法,我想相应地使测试失败。
    • 我不知道有什么方法可以直接做到这一点,对不起......想到的最好的选择是用一个模拟来存根该方法,这听起来有点傻只是说它。
    【解决方案2】:

    找到了一个很棒的宝石,可以很好地解决这个问题:

    https://github.com/bogdanvlviv/minitest-mock_expectations

    assert_called a, :c do
      a.b
    end
    

    【讨论】:

      猜你喜欢
      • 2015-06-10
      • 1970-01-01
      • 2011-12-30
      • 1970-01-01
      • 2016-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-19
      相关资源
      最近更新 更多