【发布时间】:2009-12-22 21:11:09
【问题描述】:
知道模拟 %[] 的方法吗?我正在为进行一些系统调用的代码编写测试,例如:
def log(file)
%x[git log #{file}]
end
并希望在测试此方法时避免实际执行系统调用。理想情况下,我想模拟 %x[..] 并断言正确的 shell 命令被传递给它。
【问题讨论】:
标签: ruby unit-testing mocking
知道模拟 %[] 的方法吗?我正在为进行一些系统调用的代码编写测试,例如:
def log(file)
%x[git log #{file}]
end
并希望在测试此方法时避免实际执行系统调用。理想情况下,我想模拟 %x[..] 并断言正确的 shell 命令被传递给它。
【问题讨论】:
标签: ruby unit-testing mocking
%x{…} 是 Ruby 内置语法,它实际上会调用内核方法 Backtick (`)。因此,您可以重新定义该方法。由于反引号方法返回在子 shell 中运行 cmd 的标准输出,因此您重新定义的方法应该返回类似的内容,例如字符串。
module Kernel
def `(cmd)
"call #{cmd}"
end
end
puts %x(ls)
puts `ls`
# output
# call ls
# call ls
【讨论】:
使用Mocha,如果你想模拟以下课程:
class Test
def method_under_test
system "echo 'Hello World!"
`ls -l`
end
end
您的测试将类似于:
def test_method_under_test
Test.any_instance.expects(:system).with("echo 'Hello World!'").returns('Hello World!').once
Test.any_instance.expects(:`).with("ls -l").once
end
这是因为每个对象都从 Kernel 对象继承了诸如 system 和 ` 之类的方法。
【讨论】:
should_receive 代替expects
expects(:`),而不是在Kernel上。
恐怕我不知道模拟模块的方法。至少对于 Mocha,Kernel.expects 无济于事。您可以总是将调用包装在一个类中并模拟它,如下所示:
require 'test/unit'
require 'mocha'
class SystemCaller
def self.call(cmd)
system cmd
end
end
class TestMockingSystem < Test::Unit::TestCase
def test_mocked_out_system_call
SystemCaller.expects(:call).with('dir')
SystemCaller.call "dir"
end
end
这给了我我所希望的:
Started
.
Finished in 0.0 seconds.
1 tests, 1 assertions, 0 failures, 0 errors
【讨论】:
将其记录到文本文件或将其输出到控制台怎么样?
def log(file)
puts "git log #{file}"
end
【讨论】:
你不能用一个在获取命令时返回 true 的方法来覆盖函数吗?
【讨论】: