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

。_饼干妹妹 提交于 2020-01-06 02:57:12

问题


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 => "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

回答1:


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



回答2:


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.



来源:https://stackoverflow.com/questions/1826282/rails-why-cant-i-use-a-method-i-created-in-a-module-in-my-tests

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!