这是一个关于模拟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,如何在模拟中存根,并验证其参数?
答案 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
方法。为什么?因为:
在第三行中,“ call”一词具有两种含义;和
#
中的哈希字符#call
与字母E,H和T有点相似,它们都是误读#call
所必需的:
如果 val_or_callable 响应该呼叫,则它返回调用它的结果[。]
无论如何,将通过添加“ method”一词来改进IMO文档:
如果 val_or_callable 具有#call方法,则它将返回调用它的结果[。]
在我看来,将模拟和存根结合起来时,Minitest文档中的示例(在Object#stub和Mock中)似乎有些不完整。
同样,当您验证传递给模拟的参数(使用Minitest)时,您应该使用expect
方法:call
,而不是expect
插入要使用的方法!