锁定老帖子 主题:遭遇mocha中的两个小陷阱
该帖已经被评为良好帖
|
|
---|---|
作者 | 正文 |
发表时间:2008-06-06
mocha是ruby下的一个mock框架。 关于mock object的相关信息,请参考:http://www.mockobjects.com/ 关于mocha的相关信息,请参考:http://mocha.rubyforge.org/ 基本概念及使用方法这里不谈,就谈谈最近在mocha碰到的两个小陷阱。
1.情况是这么个情况,完成了测试代码与功能代码后,我开始着手进行测试代码的重构(需要吗?不需要吗?)。首先,我盯上了刚完成测试代码时,就看着不爽的一段代码,这里整理如下: def generate_some_mock_object(return1,return2) mo=mock() mo.stubs(:mock_method1).returns(return1) mo.stubs(:mock_method2).returns(return2) mo end 这是我测试代码里的一个helper方法,用于生成一个mock对象,并stub了两个方法。味道是不怎么好,不是吗?于是,我决定重构她。扫了眼mocha的文档,发现mocha给出了一个mock对象生成的例子: product = mock('ipod_product', :manufacturer => 'ipod', :price => 100) 哇哈哈,一个hash就搞定,而且还不用定义一个额外的局部变量,happy,动手将我的helper方法改为如下形式: def generate_some_mock_object(return1,return2) mock(:mock_method1 => return1,:mock_method2 => return2) end 我happy的重新跑了一把测试,一串“F”出现在我面前,提示了一些诸如“expected call 1, not call 0”之类的错误。我就纳闷了,不都是生成一个mock对象,mock了两个stud方法么?why?仔细查看mocha文档和源代码,才发现通过mock(...)方法生成mock对象的时候,如果传递了一串excepted方法的hash时,mocha内部不用通过stubs(...)方法,生成stub方法,而是通过expects(...)方法。而expects(...)生成的方法在测试的时候必须进行调用,才认为测试通过,否则测试被认为失败的。而我的功能代码正好是只调用了{:mock_method1,:mock_method2}中的一个,所以造成测试失败。下面是mock(...)方法的源代码: def mock(*arguments, &block) name = arguments.shift if arguments.first.is_a?(String) expectations = arguments.shift || {} mock = name ? Mock.named(name, &block) : Mock.unnamed(&block) mock.expects(expectations) mocks << mock mock end 问题就出在mock.expects(expectations) 这句代码上。 def generate_some_mock_object(return1,return2) stub(:mock_method1 => return1,:mock_method2 => return2) end 重新跑一遍测试,全是"...",那个happy啊。。。stub方法的源代码如下: def stub(*arguments, &block) name = arguments.shift if arguments.first.is_a?(String) expectations = arguments.shift || {} stub = name ? Mock.named(name, &block) : Mock.unnamed(&block) stub.stubs(expectations) mocks << stub stub end 发现关键所在的stub.stubs(expectations) 代码了吧?:) PS:我发现mocha内部也有臭的迹象,mock和stub~呵呵
2.事情是这么个事情,后来,我盯上了这么一段测试代码,整理如下: def generate_some_stub_method(return1,return2) @my_object.stubs(:method1).returns(return1) @my_object.stubs(:method2).returns(return2) end 这里,@my_object不是一个mock对象,而是我实在的一个测试用的业务对象,这个helper方法无非就是为该对象生成两个stub方法,以供测试用。我仍然看她不怎么爽,同样,mocha的文档给了一个例子如下: object.stubs(:method1 => :result1, :method2 => :result2) 继续happy,又可以合二为一了。于是,我将这个helper方法重构如下: def generate_some_stub_method(return1,return2) @my_object.stubs(:method1 =>return1,:method2 => return2) end 我又happy着重新跑了一遍测试,居然提示我"{:method1 =>return1,:method2 => return2} is not a Symbol"。这个。。。老大,我承认,他绝对不是一个Symbol,但是你的示意代码和文档明明标明了stubs明明可以接受一个hash的方法集合啊?我有文档作证: stubs(method_name) → expectation class Object ...... def stubs(symbol) method = stubba_method.new(stubba_object, symbol) $stubba.stub(method) mocha.stubs(symbol, caller) end ...... end 哦!问题出在这里!我前面说了,@my_object对象不是一个mock对象,而是一个普通的oject,我只是在这个普通的object上面搞了两个stub方法上去,自然,调用的是Object#stubs方法了,而不是Mock#stubs方法。原来如此~看来,这个重构完不成了,不过还好,不算太臭,就这么着贝~ 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
浏览 4216 次