I finally got around to using a mocking library today at work. I chose Mocha to start, no real reason, just the first name to pop into my head. After about 15 minutes (10 reading docs, and 5 coding) I am in love. Seriously, testing has never been this easy. What would have taken me at least 30 minutes to add new fixtures wihtout breaking old tests or screwing anything else up was easily solved in one to 2 lines per test case.
class SupportControllerTest < ActionController::TestCase
def test_applicant_activated_view
Applicant.any_instance.expects(:activated?).returns(:true)
post :create, :applicant => {:last_name => "Leapfrog", :email => "sos_platform@leapfrogqa.com"}
assert_select "ul.activated"
end
end
The first line in the above method mocks out the activated? method on any instance of the Applicant class. Isn’t that simple and clean? Without seeing the rest of the business logic I know it might be hard to accept why I need an entire library to help me with this simple boolean method, but trust me, activated? method is actually delegated to another model which is using an ActiveResource object to truly determine the result.
Yesterday I was testing a Helper (module) I had written for a Rails app I am working on. I wanted to test the helper directly, and not deal with the whole controller and request/response loop just to verify some simple methods. So I started with something like the following:
class TrackingHelperTest < ActiveSupport::TestCase
include TrackingHelper
def test_record_event
...unimportant...
end
end
I ran into a problem almost immediately. Some of the methods in this Helper required access to the request object. At first I thought I went down the wrong path, and would need to test this Helper in the context of a controller. Then it hit me, mock the request up. But do I really need a whole class to store and share some instance variables? After pondering this for a few moments I ended up with something like this:
class TrackingHelperTest < ActiveSupport::TestCase
include TrackingHelper
# Mocks
MockRequest = Struct.new(:query_parameters, :path, :headers, :remote_ip, :path_parameters, :query_string)
attr_accessor :request
def setup
@request = MockRequest.new({}, "/some/location", {"HTTP_REFERER" => "somesite.com"}, "1.1.1.1", {:controller => "some", :action => "location"}, "")
end
def test_record_event
...unimportant...
end
end
Struct’s are simple to use and allow for quick and easy mocking in unit tests. Try it out in your code next time you don’t want to build a full class to do something simple.