开发者

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

开发者 https://www.devze.com 2022-12-13 10:25 出处:网络
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.

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号