RSpec测试没有用render_view命中视图

时间:2017-03-14 22:01:25

标签: ruby-on-rails json ruby rspec

使用RSpec在Rails控制器中测试索引操作和响应时出现此错误:     JSON::ParserError: A JSON text must at least contain two octets!

最常见的修复 - 包括render_views - 无效,nil未被传入。测试未达到视图。当我在控制器的索引操作中插入render json: {test: 'hello world'}, status: 200 and return,在视图(index.json.jbuilder)和测试中的get :index之后插入pry时,我可以看到有一个响应正文。如果我将测试期望修改为expect(response).to render_template '[]',我可以看到应该在响应主体中的空数组。为什么render_views失败以及如何让它再次运行?

这是index_spec.rb:

require 'rails_helper'

RSpec.describe ThingsController, type: :controller do
  render_views
  let(:json_response) { JSON.parse(response.body) }
  let(:status) { response.status }
  let(:user) { create(:user_with_associations) }
  subject{ ThingsController }

  describe "GET #index" do
    context "(success cases)" do
      before(:each) do
        expect_any_instance_of(subject).to receive(:set_user_by_token).and_return(user)
      end

    context "and when there are no things" do
      before(:each) do
        get :index
      end

      it "returns a 200 status" do
        expect(status).to eq 200
      end

      it "returns a top level key of data with an empty array" do
        expect(json_response["data"]).to eq []          
      end
    end
  end
end

这是rails_helper.rb:

ENV["RAILS_ENV"] ||= 'test'
require_relative 'spec_helper'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'

ActiveRecord::Migration.maintain_test_schema!

RSpec.configure do |config|
  config.fixture_path = "#{::Rails.root}/spec/fixtures"

  config.use_transactional_fixtures = true

  config.before(:suite) do
    DatabaseCleaner.strategy = :transaction
    DatabaseCleaner.clean_with(:truncation)
  end

  config.before(:each) do
    DatabaseCleaner.start
  end

  config.after(:each) do
    DatabaseCleaner.clean
  end

  config.infer_spec_type_from_file_location!
end

这是spec_helper.rb

ENV["RAILS_ENV"] ||= 'test'

require 'factory_girl_rails'
require 'faker'

include ActionDispatch::TestProcess

RSpec.configure do |config|
  config.expect_with :rspec do |expectations|
    expectations.include_chain_clauses_in_custom_matcher_descriptions = true
  end

  config.mock_with :rspec do |mocks|
    mocks.verify_partial_doubles = true
  end

  config.include FactoryGirl::Syntax::Methods

  config.before do
    FactoryGirl.factories.clear
    FactoryGirl.find_definitions
  end
end

以下是测试中的控制器操作things_controller.rb:

class ThingsController < ApplicationController

  before_action :authenticate_user!, only: [ :index ]
  before_action -> {check_last_updated("Thing")}, only: [ :index ]

  def index
    @things = @current_user.things.in_last_three_months.approved_and_unapproved.order(start_time: :asc)
  end
end

Rails 4.2.0 Ruby 2.1.2 RSpec 3.5.4

这是我的第一个问题,请告知我是否应该包含其他信息。

1 个答案:

答案 0 :(得分:2)

您未正确删除规范中的身份验证。你说

expect_any_instance_of(subject).to receive(:set_user_by_token).and_return(user)

但你应该说

allow_any_instance_of(subject).to receive(:set_user_by_token).and_return(user)

作为一般规则,应尽可能避免使用*_any_instance_of方法,因为they can be ambiguous处于更细微的情况。在控制器规范中,您可以使用controller来访问正在测试的控制器的实例。 e.g。

allow(controller).to receive(:set_user_by_token).and_return(user)