模拟系统调用红宝石

时间:2009-10-27 03:15:23

标签: ruby unit-testing mocking

知道模拟%[]的方法吗?我正在为代码进行一些系统调用的代码编写测试,例如:

def log(file)
  %x[git log #{file}]
end

并且希望在测试此方法时避免实际执行系统调用。理想情况下,我想模拟%x [..]并断言正确的shell命令传递给它。

5 个答案:

答案 0 :(得分:17)

%x{…}是Ruby内置语法,实际上会调用内核方法Backtick (`)。所以你可以重新定义这种方法。由于反引号方法在子shell中返回运行cmd的标准输出,因此重新定义的方法应该返回类似的内容,例如字符串。

module Kernel
    def `(cmd)
        "call #{cmd}"
    end
end

puts %x(ls)
puts `ls`
# output
# call ls
# call ls

答案 1 :(得分:13)

使用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

这是有效的,因为每个对象都继承了系统和`来自内核对象的方法。

答案 2 :(得分:3)

我不知道模拟模块的方法,我很害怕。至少使用摩卡,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

答案 3 :(得分:0)

如何将其记录到文本文件或将其输出到控制台?

def log(file)
  puts "git log #{file}"
end

答案 4 :(得分:-1)

你不能只用一个在获得命令时返回true的方法覆盖该函数吗?