如何从Rails 4中的帮助程序测试访问控制器帮助程序方法?

时间:2017-04-27 12:54:29

标签: ruby-on-rails ruby testing

我在ApplicationController中定义了一个方法作为辅助方法。

helper_method :can_access_participant_contact_data?

我正在尝试为辅助文件中的辅助方法编写测试。这个辅助方法调用helper_method :can_access_participant_contact_data?

# In participants_helper.rb
#
def redacted_contact_data participant, attribute_name
  attribute = participant.try(:contact_data).try(attribute_name)
  return attribute if can_access_participant_contact_data?(participant)
  return nil       if attribute.blank?
  return attribute.gsub(/\S/i, '*') # Asterisked string
end

我在测试中所做的一切都是打电话给redacted_contact_data

require 'test_helper'

class ParticipantsHelperTest < ActionView::TestCase

   test "should return an asterisked string with spaces" do
     redacted_contact_data(Participant.first, :name)
   end

end

当我运行测试时,我收到此消息

undefined method `can_access_participant_contact_data?' for #<ParticipantsHelperTest:0x007fd6c7c6d608>

我一直在四处看看,但我不确定如何解决这个问题。我需要以某种方式模仿can_access_participant_contact_data?吗?或者我可以将方法包括在测试中吗?

2 个答案:

答案 0 :(得分:1)

AFAIK(据我所知),你无法解决这个问题,如果没有存根或在你的代码中做一些改变,因为帮助文件本身只是一个自身的模块,应该独立于它的位置进行处理。将被包括在内。谁知道您可能希望在模型文件中包含此类帮助文件,例如,模型文件中也有一个名为can_access_participant_contact_data?的方法,但与ApplicationController中定义的方法不同,因此您如果不指定上下文/基础,则无法对此进行单元测试。

可能的解决方法:

  • 成株:

    • 使用Mocha或返工测试到RSpec
    • 或者通过以下方式手动(可能还有更好的方式):

      test "should return an asterisked string with spaces" do
        ParticipantsHelper.class_eval do
          define_method :can_access_participant_contact_data? do |arg|
            true
          end
        end
      
        redacted_contact_data(Participant.first, :name)
      end
      
  • 或者,将所有ApplicationController帮助程序方法移动到单独的/现有的帮助程序文件中,例如在已存在的ApplicationHelper内。然后,在您正在测试的正在使用方法的其他帮助文件中包含该帮助程序。即:

    # helpers/application_helper.rb
    module ApplicationHelper
      def can_access_participant_contact_data?(participant)
        # YOUR CODE
      end
    end
    
    # helpers/participants_helper.rb
    module ParticipantHelper
      include ApplicationHelper
    
      def redacted_contact_data participant, attribute_name
        attribute = participant.try(:contact_data).try(attribute_name)
        return attribute if can_access_participant_contact_data?(participant)
        return nil       if attribute.blank?
        return attribute.gsub(/\S/i, '*') # Asterisked string
      end
    end
    
    • 如果使用这种方法,那么有两种方法可以在控制器中调用辅助方法:

      • 在控制器中使用Rails helpers方法:

        class ParticipantsController
          def show
            helpers.can_access_participant_contact_data?(@participant)
          end
        end
        
      • 或者,直接包括帮助者(我个人更喜欢上面的其他方法)

        class ApplicationController < ActionController::Base
          include ApplicationHelper
        end
        
        class ParticipantsController < ApplicationController
          def show
            can_access_participant_contact_data?(@participant)
          end
        end
        
    • 对于视图文件,您不需要更新任何代码。

答案 1 :(得分:0)

另一种想法是在“控制器测试”中进行“帮助测试”,如下所示:

require 'test_helper'

class ParticipantsControllerTest < ActionController::TestCase
  setup do
    # do some initialization here. e.g. login, etc.
  end

  test "should return an asterisked string with spaces" do
    participant = ...
    get :show, id: participant.id
    assert_equal '...',  @controller.view_context.redacted_contact_data(...)
  end
end

@controller是ParticipantsController对象,它已经由Rails控制器测试框架定义(或者,当控制器名称与* ControllerTest不同时,您可以显式定义它),而view_context是辅助方法的对象(请参见https://api.rubyonrails.org/classes/ActionView/Rendering.html#method-i-view_context详情)。

Helper方法经常引用控制器对象和/或方法(例如会话,请求),因此有时仅在test / helpers / *中很难进行单元测试。这就是我在这种情况下在控制器中测试助手的原因。