用Ruby模拟构造函数

时间:2008-09-16 13:34:37

标签: ruby mocha

我是一名Java开发人员,玩弄Ruby并喜欢它。我已经明白,由于Ruby的元编程功能,我的单元测试变得更加清晰,我不需要讨厌的模拟框架。我有一个类需要File类的服务,在我的测试中我不想触及我的真实文件系统。在Java中,我会使用一些虚拟文件系统来更容易地“接缝”传递虚假对象,但在Ruby中显然有点过分。与Java世界相比,我的出现似乎已经非常好了。在我的测试类中,我有一个可选的构造函数参数:

def initialize(file_class=File)

当我需要在课堂上打开文件时,我可以这样做:

@file_class.open(filename)

调用转到真正的File类,或者在我的单元测试的情况下,它转到一个不接触文件系统的假类。我知道元编程必须有更好的方法吗?

3 个答案:

答案 0 :(得分:11)

Mocha(http://mocha.rubyforge.org/)是一个非常好的ruby模拟库。根据您实际想要测试的内容(例如,如果您想伪造File.new调用以避免文件系统依赖性,或者如果您想验证正确的参数是否传递到File.new),您可以执行此操作像这样的东西:


require 'mocha'

mock_file_obj = mock("My Mock File") do
  stubs(:some_instance_method).returns("foo")
end

File.stubs(:new).with(is_a(String)).returns(mock_file_obj)

答案 1 :(得分:1)

在你概述的案例中,我建议你做的事似乎没问题。我知道詹姆斯米德(摩卡的作者)提倡的这是一种技巧。没有必要为了它而进行元编程。 Here's what James has to say about it(还有一长串你可以尝试的其他技巧)

答案 2 :(得分:1)

这对我来说是一项特别困难的挑战。在我this question收到的帮助,以及我的一些额外工作,这是我到达的解决方案。

# lib/real_thing.rb
class RealThing
  def initialize a, b, c
    # ...
  end
end

# test/test_real_thing.rb
class TestRealThing < MiniTest::Unit::TestCase

  class Fake < RealThing; end

  def test_real_thing_initializer
    fake = mock()
    Fake.expects(:new).with(1, 2, 3).returns(fake)
    assert_equal fake, Fake.new(1, 2, 3)
  end

end