1

在以下测试中,我希望未登录的页面访问者获得“404”,并且响应的内容类型为 html,我表示如下:

require 'spec_helper'
require 'rspec-rails'
#require 'shoulda'
#require 'shoulda-matchers'
#require 'shoulda/matchers/action_controller'
describe StaticPagesController do
  context "home page without being logged in" do
    before { visit root_path }
    it { should respond_with :missing }
    it { should respond_with_content_type :html }
    it { should_not render_template :application }
    it { should_not render_with_layout }
    it { should_not set_the_flash }
  end
end

这是被测控制器:

class StaticPagesController < ApplicationController
  def home
    if signed_in?
      redirect_to user_path
    else
      render layout: false,
             file: %Q(#{ Rails.root }/public/404),
             formats: [:html],
             status: '404'
    end
  end
end

当我执行测试时,respond_withrespond_with_content_type匹配器失败

NoMethodError: undefined method `content_type' for nil:NilClass
/home/rev/.rvm/gems/ruby-1.9.3-p194/gems/shoulda-matchers-\
1.4.2/lib/shoulda/matchers/action_controller/\
respond_with_content_type_matcher.rb:59:in `response_content_type'

NoMethodError: undefined method `response_code' for nil:NilClass
/home/rev/.rvm/gems/ruby-1.9.3-p194/gems/shoulda-matchers-\ 
1.4.2/lib/shoulda/matchers/action_controller/respond_with_matcher.rb:57:
in `response_code'

这对我来说很奇怪,因为这些方法是:

    def response_content_type
      @controller.response.content_type.to_s
    end

    def response_code
      @controller.response.response_code
    end

这意味着@controller' 的响应为空或@controller为零,这是可能的,但不反映我在浏览器中看到的行为。

我的猜测,考虑到我在这方面是一个完整的 n00b(一般是 Ruby/Rails/RSpec/etc/MVC 开发),是我忘记了一两个 gem,或者我做了其他愚蠢的事情,但我猜不出是什么,几天的搜索也没有找到任何有用的线索。这是当前的 gem 环境:

 thor (0.16.0)
 bundler (1.2.1)
 childprocess (0.3.6)
 sprockets (2.2.2)
 rspec-mocks (2.12.1)
 rspec (2.12.0)
 selenium-webdriver (2.27.2)
 actionmailer (3.2.11)
 rdoc (3.12)
 polyglot (0.3.3)
 shoulda-matchers (1.4.2)
 mocha (0.10.5)
 rack-ssl (1.3.2)
 metaclass (0.0.1)
 shoulda-context (1.0.2)
 bcrypt-ruby (3.0.1)
 mime-types (1.19)
 websocket (1.0.6)
 rspec-rails (2.12.2)
 rspec-expectations (2.12.1)
 rack-test (0.6.2)
 lumberjack (1.0.2)
 treetop (1.4.12)
 stream (0.5)
 sass (3.2.5)
 listen (0.7.2)
 guard-rspec (2.4.0)
 bourne (1.1.2)
 xpath (1.0.0)
 uglifier (1.3.0)
 mail (2.4.4)
 nokogiri (1.5.6)
 activeresource (3.2.11)
 journey (1.0.4)
 rails (3.2.11)
 i18n (0.6.1)
 coderay (1.0.8)
 activemodel (3.2.11)
 activerecord (3.2.11)
 libwebsocket (0.1.7.1)
 rack-cache (1.2)
 builder (3.0.4)
 guard (1.6.1)
 rake (10.0.3)
 bootstrap-sass (2.2.2.0)
 coffee-script-source (1.4.0)
 slop (3.4.3)
 active_attr (0.7.0)
 rack (1.4.4)
 debugger-ruby_core_source (1.1.6)
 debugger (1.2.3)
 columnize (0.3.6)
 coffee-script (2.2.0)
 ffi (1.3.1)
 shoulda (3.3.2)
 sass-rails (3.2.6)
 arel (3.0.2)
 jquery-rails (2.1.4)
 debugger-linecache (1.1.2)
 tilt (1.3.3)
 coffee-rails (3.2.2)
 hike (1.2.1)
 actionpack (3.2.11)
 rb-inotify (0.8.8)
 railties (3.2.11)
 pry (0.9.11.2)
 rspec-core (2.12.2)
 rgl (0.4.0)
 diff-lcs (1.1.3)
 activesupport (3.2.11)
 addressable (2.3.2)
 libnotify (0.5.9)
 capybara (2.0.2)
 json (1.7.6)
 erubis (2.7.0)
 guard-spork (1.4.1)
 execjs (1.4.0)
 multi_json (1.5.0)
 tzinfo (0.3.35)
 spork (0.9.2)
 sqlite3 (1.3.7)
 method_source (0.8.1)
 rubyzip (0.9.9)

如果我遗漏了以上任何有用的信息,请告诉我。

关于如何确定为什么@controller或者@controller.response应该是 nil 的任何建议?我粗略地追踪处决的尝试没有成功。

提前致谢,

德雷尔

4

1 回答 1

1

尝试替换before { visit root_path }before { get :home }.

“访问”语法通常与 Capybara 和 Webrat 等库提供的完整堆栈接受规范一起使用。RSpec 提供了一个特殊的上下文和辅助方法来执行控制器规范中的单个操作,您可以在此处阅读更多信息:https ://www.relishapp.com/rspec/rspec-rails/v/2-12-2/docs /控制器规格。调用get(:home)将模拟对被测控制器的“home”操作的 GET 请求。我相信这将@controller在引擎盖下设置,正如您的应该匹配器所期望的那样。

user_signed_in?您可能还需要模拟登录用户以测试控制器操作中的真假情况。如果您使用的是 Devise,Devise wiki有一个很好的关于设置 RSpec 控制器规范的演练。

于 2013-01-18T05:03:35.780 回答