如何测试使用系统命令的代码

时间:2011-03-16 14:48:42

标签: ruby-on-rails ruby unit-testing testing

我正在编写一个简单的库来检查mysql服务器是否存活并依赖于结果,它会做其他事情。要检查连接,我使用这样的代码:

def check_connection
  result = if @password
    `mysqladmin -u#{@username} -p#{@password} ping`
  else 
    `mysqladmin -u#{@username} ping` 
  end
  parse_result(result)
end

如何测试此方法?我想,我不应该在测试期间连接到mysql服务器。我只有想法是在一个方法中返回适当的字符串命令用于ping(取决于密码用法)并在以下方法中使用它:

def check_connection(ping_string)
  `#{ping_string}`
end

并且在每个测试中只模拟这个方法,因此只有这个方法使用命令。

你会做什么来正确测试它?

2 个答案:

答案 0 :(得分:1)

您可以坚持使用原始代码,并按照以下方式处理:

  1. 确保parse_result已经过单元测试。
  2. 模拟check_connection,以便其余测试不会最终触发对mysqladmin的调用。
  3. 有一个漏洞,与mysql本身的连接没有经过测试,但我不认为这是一个大问题。测试ping_string不会真正堵塞这个漏洞,并且鉴于对mysqladmin的调用基本上是硬编码的,因此您的风险很小。

答案 1 :(得分:0)

如果使用system命令而不是反引号(``),则可以在测试中将其存根。所以假设你有这个课程:

class Thing
  def check_connection
    result = system "some command"
    parse_result result
  end
end

在你的测试中(我将使用rspec语法进行说明)你可以像这样测试它:

it 'should check the connection' do
  thing = Thing.new
  thing.should_receive(:system).and_return "some result"

  thing.check_connection
  # whatever checking you want to make with the parse_result method
end

这是有效的,因为通常系统方法会传递到Kernel#system,这会进行真正的系统调用。在测试中,您允许Thing的实例使用您可以从实际调用中获得的某些输出来响应系统方法。