我有一个非常简单的控制器,看起来像这样。
module Veterinarians
module Dictionaries
class SpecialitiesController < ApplicationController
respond_to :json
skip_before_action :check_current_vet, only: %i( index )
def index
@specialities = Veterinarians::Speciality.all
respond_with(@specialities)
end
end
end
end
我有一个看起来像这样的rspec控制器测试。
require 'rails_helper'
Rails.describe Veterinarians::Dictionaries::SpecialitiesController, type: :controller do
# Not returning a response body in JSON when testing RSPEC (https://github.com/rails/jbuilder/issues/32)
render_views true
routes { Veterinarians::Engine.routes }
let(:user) { double :user, id: 123 }
before { sign_in(user) }
context '#index' do
let(:speciality) { double :speciality, id: :some_id, value: :some_val }
before { allow(Veterinarians::Speciality).to receive(:all).and_return [speciality] }
subject { get :index, format: :json }
it { is_expected.to have_http_status(:ok) }
it { expect(JSON.parse(subject.body)).to include('id' => 'some_id', 'value' => 'some_val') }
end
end
第二个示例失败,出现此错误。
expected [{"__expired" => false, "name" => "speciality"}] to include {"id" => "some_id", "value" => "some_val"}
关于为什么会失败以及带有“__expired”的散列来自哪里的任何提示?
我有其他测试正在使用相同的测试方法,这些测试是成功的。
我怀疑这是来自RSpec的双重内部表示:
https://github.com/rspec/rspec-mocks/blob/master/lib/rspec/mocks/test_double.rb#L10
RSpec的双打有时与Rails一起运行不佳。尝试实例化一个真正的Speciality
实例,或使用像FactoryGirl这样的东西。
Rails最终将to_json
称为双击。你还没有在double上找到那个方法,所以调用to_json
方法rails添加到Object
。
这个implementation只是转储对象的实例变量,在这种情况下是测试double的内部状态。
你可以在双倍上存根to_json
,虽然你的规范在这一点上不会测试很多。
您应该使用工厂来创建测试数据。两个最受欢迎的是FactoryGirl或FactoryBot。
例:
FactoryGirl.define do
factory :user do
sequence(:email) { |n| "name#{n}@example.com" }
password 'password'
end
end
sequence(:email)
将为每个用户创建一个不同的电子邮件。更多细节可以在here找到。