我是一名Java开发人员,玩弄Ruby并喜欢它。我已经明白,由于Ruby的元编程功能,我的单元测试变得更加清晰,我不需要讨厌的模拟框架。我有一个类需要File
类的服务,在我的测试中我不想触及我的真实文件系统。在Java中,我会使用一些虚拟文件系统来更容易地“接缝”传递虚假对象,但在Ruby中显然有点过分。与Java世界相比,我的出现似乎已经非常好了。在我的测试类中,我有一个可选的构造函数参数:
def initialize(file_class=File)
当我需要在课堂上打开文件时,我可以这样做:
@file_class.open(filename)
调用转到真正的File类,或者在我的单元测试的情况下,它转到一个不接触文件系统的假类。我知道元编程必须有更好的方法吗?
答案 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