【问题标题】:Minitest: how to stub with a mock, and verify its argumentsMinitest:如何使用模拟存根,并验证其参数
【发布时间】:2019-01-03 20:03:35
【问题描述】:

这是一个关于模拟module Email 类方法的小例子。方法名为connect_and_send

require 'minitest/autorun'
module Email
  def self.connect_and_send(*args)
    nil
  end
end
class Test < Minitest::Test
  def test_it
    fake = Minitest::Mock.new
    fake.expect :connect_and_send, nil, ['a', 'b', 'c']
    Email.stub :connect_and_send, fake do
      Email.connect_and_send 'a', 'b', 'z'
    end
    fake.verify
  end
end

该示例旨在验证方法及其参数是否被调用。

但它会产生一条错误消息,提示 connect_and_send 是预期的,但没有被调用!

  1) Error:
Test#test_it:
MockExpectationError: expected connect_and_send("a", "b", "c") => nil
    -:14:in 'test_it'

1 runs, 0 assertions, 0 failures, 1 errors, 0 skips

相反,我认为它会产生一条错误消息,指出方法 (connect_and_send) 的参数不正确。

使用 Minitest,我如何使用 mock 存根并验证其参数?

【问题讨论】:

    标签: ruby mocking arguments minitest stubbing


    【解决方案1】:

    答案是expect 方法:call,而不是expecting 方法connect_and_send。以下代码:

    require 'minitest/autorun'
    module Email
      def self.connect_and_send(*args)
        nil
      end
    end
    class Test < Minitest::Test
      def test_it
        fake = Minitest::Mock.new
        fake.expect :call, nil, ['a', 'b', 'c']
        Email.stub :connect_and_send, fake do
          Email.connect_and_send 'a', 'b', 'z'
        end
        fake.verify
      end
    end
    

    以所需的方式验证将哪些参数传递给方法connect_and_send

    它给出了正确的错误消息,即存根方法被传递了不正确的参数:

      1) Error:
    Test#test_it:
    MockExpectationError: mocked method :call called with unexpected arguments ["a", "b", "z"]
        -:12:in 'block in test_it'
        -:11:in 'test_it'
    
    1 runs, 0 assertions, 0 failures, 1 errors, 0 skips
    

    并且证明被测代码调用了方法connect_and_send

    如果一个对象有多个您希望存根的方法(在验证它们的参数时),那么使用多个模拟。

    这是 Minitest 的 Object#stub 文档。从技术上讲它是正确的,当它的第二个参数says 时(见第三行):

    #stub(名称,val_or_callable,*block_args)⇒ 对象

    添加一个临时存根方法,在 block 期间替换 name
    如果val_or_callable响应#call,则返回调用结果[.]

    然而,我想很多人(和我一样)会误读这个短语中的文档,因为它是对存根方法的“调用”,例如——在这个例子中——connect_and_send 方法。为什么?因为:

    1. 在第三行中,“呼叫”一词有两种含义;和

    2. #call 中的哈希字符 # 与字母 E、H 和 T 中的每一个都略有相似,这些都是必需的,以便将 #call 误读为:

    如果val_or_callable响应调用,则返回调用结果[.]

    无论如何,IMO 的文档将通过添加“方法”一词得到改进:

    如果val_or_callable有#call方法,则返回调用结果[.]

    在我看来,Minitest 文档(Object#stubMock)中的示例在模拟和存根结合使用时可能看起来有些不完整。

    同样,当您验证传递给您的模拟的参数时(使用 Minitest),您应该 expect 方法 :call,而不是 expecting 您正在存根的方法!

    【讨论】:

    • 有没有办法查看预期参数和接收参数之间的差异?
    猜你喜欢
    • 2017-02-14
    • 2018-10-01
    • 2012-07-27
    • 1970-01-01
    • 2017-11-02
    • 2014-12-28
    • 1970-01-01
    • 2017-03-01
    • 1970-01-01
    相关资源
    最近更新 更多