使用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
这是我的第一个问题,请告知我是否应该包含其他信息。
答案 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)