如何创建控制器规范来测试未经授权的访问,重定向和消息

时间:2016-03-15 13:27:36

标签: ruby-on-rails rspec devise cancan

我正在尝试创建控制器规范,在这种情况下,对于未授权访问此资源的用户。我需要检测重定向的状态,位置以及来自Devise / Cancan的消息。

经过多次黑客攻击后,我想出了这个。

context 'with unauthorized user' do
  describe 'GET #index' do
    subject { xhr :get, :index, {} }
    it { subject; response.status.should eq 401 } #successfully detects unauthorized
    it { should redirect_to new_user_session_path } #Expected response to be a <redirect>, but was <401>
    it 'redirects' do 
      get :index, {}
      expect(response).to redirect_to(new_user_session_path) #successfully detects redirect
      # how to get the Devise message?
    end
  end
end

有人可以帮我理解这里发生的事情。

  1. xhr :get, :indexget :index, {}之间有什么区别。
  2. subject; response.status.should eq 401和`response.status.should eq 401&#39;
  3. 之间有什么区别?
  4. 如何从回复中获取消息?

1 个答案:

答案 0 :(得分:2)

Controller specs存根应用程序的许多层。例如,他们实际上并不创建HTTP请求或通过路由层。它们也默认不渲染视图。这使得测试更快一些,但是存根确实在测试敏锐度方面有成本。

get :foo创建一个伪造HTTP请求的请求对象。 Rails通过查看您的路线并尝试找到与params相匹配的东西来做到这一点。 xhr :foo大致相同,但会设置请求标头,因此它似乎是XHR请求。

redirect_to 匹配器测试响应是HTTP重定向。这意味着响应代码应该在300-399范围内并包含位置标题。

要测试其他响应代码,您应该执行以下操作:

context 'with unauthorized user' do  
  describe 'GET #index' do
    before { get :index }
    subject { response }
    it { is_expected.to have_http_status 401 } 
    it "redirects to login" do
      expect(response.headers[:location]).to equal new_user_session_path
    end
  end
end

如何从响应中获取消息?

答案很简单,就是在上下文中使用render_views,它会在response.body中为您提供正文。但是,由于实际上没有遵循重定向,因此这将无法正常工作。

考虑使用功能规范来测试此行为:

RSpec.feature "Foos" do
  context "A guest" do
    scenario "should not be able to view all Foos" do
      visit "/foos"
      expect(response).to have_content "You are not allowed to view this page"
    end
  end
end