【问题标题】:Rails rspec controller test is returning an unknown hashRails rspec 控制器测试返回未知哈希
【发布时间】:2016-05-13 18:27:33
【问题描述】:

我有一个非常简单的控制器,看起来像这样。

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" =&gt; false, "name" =&gt; "speciality"}] to include {"id" =&gt; "some_id", "value" =&gt; "some_val"}

关于为什么这会失败以及带有“__expired”的哈希来自哪里的任何提示?

我还有其他使用相同测试方法成功的测试。

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-4 rspec


    【解决方案1】:

    我怀疑这是来自 RSpec 的双重内部表示:

    https://github.com/rspec/rspec-mocks/blob/master/lib/rspec/mocks/test_double.rb#L10

    RSpec 的双打有时不能与 Rails 一起很好地工作。尝试实例化一个真正的 Speciality 实例,或使用类似 FactoryGirl 的东西来这样做。

    【讨论】:

      【解决方案2】:

      Rails 在替补席上最终致电 to_json。您还没有在 double 上存根该方法,因此调用了 rails 添加到 Objectto_json 方法。

      implementation 只是转储对象的实例变量,在这种情况下是测试替身的内部状态。

      您可以将 to_json 存根在双精度上,尽管此时您的规范不会进行大量测试。

      【讨论】:

        【解决方案3】:

        您应该使用工厂来创建测试数据。最受欢迎的两个是 FactoryGirl 或 FactoryBot。

        例子:

        FactoryGirl.define do
          factory :user do
            sequence(:email) { |n| "name#{n}@example.com" }
            password 'password'
          end
        end
        

        sequence(:email) 将为每个用户创建不同的电子邮件。更多详情请见here

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-12-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多