Mock object standard?

I see a lot of discussion from a few years ago about Mock objects but
I’m unclear if there was any decision made. What is everyone using for
this?

I see a lot of Java based mock software ported over and it didn’t look
like the full power of Ruby was utilized. I’m speaking as someone who
has only read through the blogs today so if I’m off base just send me
plenty of hate responses.

I personally like Java’s EasyMock and I found that the usage can be
cleaned up nicely in Ruby. Here’s a comparison of the usage of the
real EasyMock and class I just created to do the same thing for me.

Given a fictious DAO which retrieves and updates user names by id:

Java:

// setup
private MockControl userDaoControl =
MockControl.createControl(UserDao.class);
private UserDao userDao = (UserDao) userDaoControl.getMock();

// training phase
userDao.find_name(1);
userDaoControl.setReturnValue(“Bob”);
userDao.update_name(-1, “Bobby”);
userDaoControl.setThrowable(new RuntimeException(“user not found”));
userDaoControl.replay();

// now use the mock
assertEquals(“Bob”, userDao.find_name(1));
// i don’t know an easy way to test exceptions in junit3.8
// i’ll spare you the nasty try/fail/catch that is generally done.
userDaoControl.verify();

Ruby:

setup - note no interface/class pass in necessary

userDao = Test::Unit::EasyMock.new

training

userDao.expects do |mock|
mock.find_name(1) {return “Bob”}
mock.update_name(-1, “Bobby”) {raise “user not found”}
end

use

assert_equal “Bob”, userDao.find_name(1)
assert_raise(RuntimeError) { userDao.update_name(-1, “Bobby”)}
userDao.verify


The amazing thing is the code for this is ~40 lines. I say this only
to point out that duck typing rocks for mock objects.

The use of blocks to specify what should happen when a method is
called is so nice as it allows arbitrary code to be executed. You
could specify multiple things to happen before the return if desired
allowing you to make mocks arbitrarily complicated. (Although I
couldn’t get “yield” to work since it seems to be a well known problem
with “call” on a Proc like: lambda {yield “hello”})

The use of a block to specify the training phase is also nice, I
believe. Thereafter this mock should behave like the object being
mocked as specified.

Anyway - let me know if I’m re-inventing the wheel or not. I’ll likely
post the code on my blog tomorrow after some sleep and another shot at
the yield issue.

  • Byron

Have you looked at Flex Mock?

http://onestepback.org/software/flexmock/

Or Mocha (http://mocha.rubyforge.org) & RSpec
(http://rspec.rubyforge.org).