Search code examples
ruby-on-railsrubymixins

Rails - Why can't I use a method I created in a module in my tests?


I created a module in lib directory and I can freely call the various methods it contains throughout my Rails app (after adding include ModuleName) with no problems.

However when it comes to tests, they complain no such methods exist. I tried including the module into my test helper with no luck. Can anyone help.

4) Error:
test_valid_signup_redirects_user_to_spreedly(UsersControllerTest):
NoMethodError: undefined method `spreedly_signup_url' for SpreedlyTools:Module
    /test/functional/user_controller_test.rb:119:in `test_valid_signup_redirects_user_to_spreedly'

module SpreedlyTools
  protected
  def spreedly_signup_url(user)
    return "blahblah"
  end
end

class ApplicationController < ActionController::Base


  helper :all # include all helpers, all the time
  protect_from_forgery # See ActionController::RequestForgeryProtection for details
  include SpreedlyTools
  ....
end

ENV["RAILS_ENV"] = "test"
require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
require 'test_help'

class ActiveSupport::TestCase
   include SpreedlyTools
   ....
end

require File.dirname(__FILE__) + '/../test_helper'
require 'users_controller'

# Re-raise errors caught by the controller.
class UsersController; def rescue_action(e) raise e end; end

class UsersControllerTest < ActionController::TestCase
....

  def test_valid_signup_redirects_user_to_spreedly
    get :new
    assert_response :success
    post :create, :user =>  {:first_name => "bobby",
                      :last_name => "brown",
                      :email => "[email protected]",
                      :email_confirmation => "[email protected]",
                      :password => "bobby1",
                      :password_confirmation => "bobby1"}

    assert_response :redirect
    user = assigns(:user)
    assert_redirected_to SpreedlyTools.spreedly_signup_url(user)

  end
end

Solution

  • There are a couple of different errors here. First, when you create a module and you mix the content of the module into a class, the methods within the module become part of the class itself.

    That said, the following line doesn't make sense

    assert_redirected_to SpreedlyTools.spreedly_signup_url(user)
    

    Assuming you mixed the module into a User class, you should call the method as

    assert_redirected_to User.new.spreedly_signup_url(user)
    

    Also note the new statement. Because you include the module into the class and you don't extend the class, the method become an instance method not a class method.

    assert_redirected_to User.new.spreedly_signup_url(user) # valid
    assert_redirected_to User.spreedly_signup_url(user) # invalid
    

    For this reason, the following line doesn't make sense.

    class ActiveSupport::TestCase
       include SpreedlyTools
       ....
    end