最小测试:如何对模拟进行存根并验证其参数

时间:2018-07-26 18:27:21

标签: ruby mocking arguments minitest stubbing

这是一个关于模拟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,如何在模拟中存根,并验证其参数?

1 个答案:

答案 0 :(得分:0)

答案是expect方法:call,而不是expect方法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方法。

如果一个对象有多种方法,希望在验证其参数的同时进行存根处理,则可以使用多个模拟。

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

  
    

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

  
     

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

但是,我想很多人(和我一样)都会误读该短语中的文档,这意味着,而是对存根方法的“调用”,例如connect_and_send方法。为什么?因为:

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

  2. #中的哈希字符#call与字母E,H和T有点相似,它们都是误读#call所必需的:

  

如果 val_or_callable 响应该呼叫,则它返回调用它的结果[。]

无论如何,将通过添加“ method”一词来改进IMO文档:

  

如果 val_or_callable 具有#call方法,则它将返回调用它的结果[。]

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

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