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 cal开发者_开发技巧l 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 => "bobby.brown@gmail.com",
:email_confirmation => "bobby.brown@gmail.com",
:password => "bobby1",
:password_confirmation => "bobby1"}
assert_response :redirect
user = assigns(:user)
assert_redirected_to SpreedlyTools.spreedly_signup_url(user)
end
end
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
Ah, it's a subtle problem but easily corrected. Rather than including SpreedlyTools in your test suite you want to test objects that were created by classes that include SpreedlyTools.
In Ruby you may find that Classes work a lot more the way you're thinking Modules work. You can use a class level function by defining it as such:
class SpreedlyTools
def self.spreedly_signup_url user
...
end
end
SpreedlyTools.spreedly_signup_url user
This would make sense now.
Modules are for mixing in code to other classes. But if you just want generic tools available at all times you really want class level functions.
精彩评论