【问题标题】:Mocking authlogic from shoulda with mocha用 mocha 从 shoulda 模拟 authlogic
【发布时间】:2010-09-07 10:24:59
【问题描述】:

我在从 shoulda 模拟 authlogic 时遇到问题。

我有以下测试夹具:

class HomeControllerTest < ActionController::TestCase
  context "on GET to index" do
    setup do
      activate_authlogic
      UserSession.stubs(:current_user).returns( user_session )
      get :index
    end

    should respond_with :success
  end

  def user_session
    @user_session.stubs(:user).returns(Factory.build(:user))
    @user_session.stubs(:record)
    @user_session
  end
end

问题是 ApplicationController 中的 require_user 方法仍然没有得到 current_user。

def current_user
  puts "#{defined?(@current_user)}"
  return @current_user if defined?(@current_user)
  @current_user = current_user_session && current_user_session.record
end

def require_user
  unless current_user
    store_location
    flash[:notice] = "You must be logged in to access this page"
    redirect_to login_url
    return false
  end
end

谁能看出哪里出了问题?

【问题讨论】:

    标签: ruby-on-rails authlogic mocha.js


    【解决方案1】:

    我认为问题可能出在您的 current_user 方法的最后一行。

    您可能希望将其拆分为几行,以使其更具可读性并且更容易诊断该语句的哪些部分与您在测试中所期望的不同。

    例如

    @current_user = current_user_session
    @current_user.record if @current_user
    return @current_user
    

    【讨论】:

    • current_user 方法的最后一行是直接出自AuthLogic。在 Ruby 中,像 result = foo &amp;&amp; foo.bar 这样的行是“将变量 result 的值设置为 foo 对象的 bar 属性,但前提是设置了 foo 变量”的便捷简写。如果未设置 foo,foo &amp;&amp; foo.bar 将返回 nil。如果设置了 foo,则返回 foo.bar 的值。
    • 很公平,但我仍然认为将其扩展为更多行将更容易找出测试中出了什么问题。我已更新我的答案以删除不正确的返回值假设。
    • 另外,current_user 方法的返回值不是current_user_session.record 的值吗?如果存根出现问题,很可能是nil
    • 你说对了一部分。 current_user_session.record 返回一个 User 对象。但是,在此测试场景中,current_user_session 将是 nil。因此,current_user_session &amp;&amp; ... 将返回 nil,从而将 @current_user 设置为 nil。
    • 查看 github.com/binarylogic/authlogic_example/blob/master/app/… 以查看 ApplicationController 中 AuthLogic 的基本实现。
    【解决方案2】:

    看起来你的模拟有点混乱;它正在模拟一个User 对象(但您使用的实例变量称为@user_session),然后在该用户上存根#record 方法。

    此外,您正在模拟 UserSession 控制器上的 current_user 方法,而它实际上是在 ApplicationController 上定义的。

    您在测试中试图断言的是用户必须登录才能访问 Home#index 页面。在这个测试中,您不应该关注 UserSession 对象——它没有那么重要。 重要的是,如果系统识别出用户对象已被检索并标识为“current_user”,则应允许他们访问该页面。

    以下规范可能适合您:

    class HomeControllerTest < ActionController::TestCase
      context "on GET to index" do
        setup do
          activate_authlogic
          @user = Factory.build(:user)
          login_as_user(@user)
    
          @controller.should_receive(:current_user).and_return(@user)
    
          get :index
        end
    
        should respond_with :success
      end
    
      def login_as_user(user = Factory.build(:user))
        @controller.stubs(:current_user).returns(user)
      end
    end
    

    我正在使用 ActionController::TestCase 为您提供的@controller 变量。它代表正在测试的当前控制器的实例。

    这里要注意的重要一点是——除了第 4 行——这个测试现在并不关心你使用什么来提供身份验证功能。只要您的应用程序定义了一个返回 User 对象或 nil 的 current_user 方法,您就可以使用 AuthLogic、Devise 或任何其他解决方案,并且您的测试将继续按预期工作。

    【讨论】:

      猜你喜欢
      • 2011-04-21
      • 1970-01-01
      • 1970-01-01
      • 2023-02-09
      • 1970-01-01
      • 1970-01-01
      • 2019-07-28
      • 2015-10-21
      • 1970-01-01
      相关资源
      最近更新 更多