To prevent bots from Signing up on our application, we added a captcha to our User model. We used the validates_captcha plugin available at http://svn.2750flesk.com/validates_captcha/trunk
The plugin, selects text from a String array for the captcha challenges, so, Sur, my co-programmer, hacked the plugin a little to add random text and improved images.
After adding the plugin we realized that all our tests which validate the User model had started failing. Programmatcially a test case or a bot are not much different, they are both scripts.
Mocks to the rescue.
Here is what I wrote in a file named add_captcha_to_active_record.rb under test/mocks/test directory.
require File.expand_path(File.dirname(__FILE__) +
"/../../../vendor/plugins/validate_captcha/lib/add_captcha_to_active_record")
module AngryMidgetPluginsInc #:nodoc:
module Validations #:nodoc:
# module Captcha
module Captcha #:nodoc:
# module InstanceMethods
module InstanceMethods #:nodoc:
private
def validate_captcha(options = {}) #:nodoc:
end
end
end#module Captcha
end#module Validations
end#module AngryMidgetPluginsInc
What I have done by adding this file is, I have asked the test scripts to use the validates_captcha method in /test/mocks/test/add_captcha_to_active_record.rb instead of the validates_captcha method in plugins/validate_captcha/lib/add_captcha_to_active_record.rb
Well actually Rails does all the magic, I just need to give the same file name as the one I want to mock and then define the method that I want to override.
The original validates_captcha method checks that the text entered on the signup screen is the same as that stored on the server. If these do not match it adds a validation error to the base class, the User class in our case.
In the mock validates_captcha method we just do nothing. So a validation error will never be added to the base class.
And now our tests are running and passing again.
I also noted the presence of a directory /test/mocks/development/ … well that means I can even mock classes in the development environment.
One of our application, connects to Paypal to make a payment and then returns back. During development we had commented out this code so that we are not sent to paypal everytime. Now I know how I can avoid commenting or changing the code by using mock objects.
I will be working on that soon and blog about my experiences here.