Plugins - active_mocks
Add to favoritesactive_mocks is intended to help in menial mockery with ActiveRecord objects when fiddling with unit and/or functional tests. Mocking AR objects is sometimes a tad tedious. For example, consider a scenario, where you wish to mock an item which has an associated thingy, attributes of which you need to access. You might whip up something similar to the following:
def test_something_important
company = flexmock('Company') do |m| # ar object to mock
m.should_receive(:new_record?).and_return(false)
m.should_receive(:users).and_return {
[
flexmock('User', :name => 'Joe'),
flexmock('User', :name => 'Bob'),
flexmock('User', :name => 'Alice')
]
}
end
# do stuff with company mock object
end
yet it is not enough in many cases; when using associations Rails gets inquisitive by checking types and raises an error in case of class mismatch, so you’d need to mock that too.
How to Mock a Mockingbird
Enter active_mocks. To use, just add line ‘include ActiveMock’ after reopening Test::Unit::TestCase in test/test_helper.rb:
class Test::Unit::TestCase
include ActiveMock
(no need to say anything about flexmock, it is required in active_mocks.rb)
Usage examples
Roughly from the simpler to just slightly more complex ones:
require 'mycompiler'
compiler = activemock(:my_compiler) # or activemock('MyCompiler') works too
assert compiler.is_a?(MyCompiler)
# each mock has a default name but it can be overridden
assert_equal 'some jedi', activemock(:jedi).name
assert_equal 'Luke Skywalker', activemock(:jedi, :name => 'Luke Skywalker')
# first level associations are quite easy
company = activemock(:company, :has_many_people)
assert_equal [], company.names
company = activemock(:company,
:has_many_people_with_names => ['joe', 'jack', 'jill'])
assert_equal 'joe', company.people.first.name
assert_equal 2, company.people.select {|p| p.name.length == 4}.length
# belongs to works as well
user = activemock(:user,
:belongs_to_company_with_owner => 'Gill Bates')
assert_equal 'Gill Bates', user.company.owner
# and is nil if nothing specified
user = activemock(:user, :belongs_to_company)
assert_nil user.company
# finally (and most convenient perhaps) is that you can specify first level
# association mocks fill full hash, allowing you to specify many attributes and
# expected values easily:
user = activemock(:user,
:has_many_friends => [
{:name => 'Jill', :age => 31},
{:name => 'Bob', :age => 27},
{:name => 'Alice', :age => 42},
{:name => 'Rob', :age => 33}
]
)
user_jill = user.friends.find {|u| u.name == 'Jill'}
assert_equal 31, user_jill.age
assert_equal 4, user.friends.length
Note that activemock is just a wrapper over flexmock and options you pass to activemock are passed to flexmock as well (with the exception of special association symbols).
Oh, and I’ve alias_method ‘d activemock to just mock in my test suites, so you can save even more in typing.
Bugs
Probably some, haven’t found yet (patches with matching test cases are welcome!)
Licence: MIT (attached)
Edvard Majakari
http://majakari.net/code/plugin-active_mocks
svn://majakari.net/public/rails/plugins/active_mocks/trunk
Rails' (MIT)
Testing
