什么是单独测试rails控制器的正确方法?

时间:2014-04-11 01:44:36

标签: ruby-on-rails unit-testing controller

即使是看似简单的索引操作也会让人感到非常复杂,无法单独测试。 我发现自己不得不嘲笑我的UserTenant几种方法,只是为了通过before_filter。然后我需要模拟KaminariTenant#users来执行操作。

对于没有控制流的测试控制器动作,这感觉太过分了。

TDD原则会说过度需要嘲笑是设计不佳的标志,但后来我不确定如何将这个功能提取到域对象中。

这是测试Rails控制器的这种痛苦的模拟标准吗?有没有更好的方法来做到这一点,我根本不知道?

例如,跳过before_filter可能会减少痛苦,但由于它们是相应的私人方法,我觉得跳过它们是不合适的。

  class UsersController < AdminController
    before_filter :check_auth
    before_filter :check_admin
    around_filter :set_tenant_time_zone, if: current_tenant

    def index
      Kaminari.paginate(current_tenant.users).page(params[:page])
    end

    private

    def current_user
      # gets user from session
    end

    def current_tenant
      current_user.tenant if current_user
    end

    def set_tenant_time_zone
      Time.use_zone(current_tenant.time_zone, &block)
    end

    def check_auth
      redirect_to login_url unless AuthChecker.new(current_user, request.remote_ip).has_access?
    end

    def check_admin
      redirect_to root_url unless current_user.is_admin?
    end
  end

1 个答案:

答案 0 :(得分:1)

如果你想运行那些before_filters,你必须做所有那些模拟/存根但是我认为,对于那些情况,最好使用一些规范帮助方法来创建一个登录用户,因此,根据你的规范,你只需要在&#34;之前调用该方法(:每个)&#34;您想要用户的控制器块。

在spec_helper.rb中:

def current_user(stubs = {})
  unless @current_user
    u = FactoryGirl.build(:user, stubs)
    u.save(:validate => false)
    @current_user = u
  end
  @current_user
end

def current_user_session(stubs = {}, user_stubs = {})
  @current_session ||= mock_model("Session", {:record => nil, :user => current_user(user_stubs)}.merge(stubs))
end

def login(session_stubs = {}, user_stubs = {})
  UserSession.stub(:find).and_return(current_user_session(session_stubs, user_stubs))
  controller.stub(:current_user => @current_user)
end

所以,在需要登录用户的控制器规范上我可以做一些特殊的存根

describe 'GET index' do
  before(:each) do
    login #this does all you need to pass the filters
  end

  it 'does something' do
    current_user.stub(:some_method)
    get :index
    expect(response).to something
  end
end

那样测试只有操作的实际代码的存根,实例和期望而不是过滤器