【问题标题】:Rspec objects comparation fails (Ruby on Rails)Rspec 对象比较失败(Ruby on Rails)
【发布时间】:2015-11-16 09:05:15
【问题描述】:

我编写了一个简单的规范来测试带有无效属性更新操作。我希望 obj 属性保持不变,但由于某些奇怪的原因测试失败,尽管属性仍然相同。

感谢您的建议。

规格

require 'rails_helper'

RSpec.describe Api::V1::PatientsController, type: :controller  do

    # ...

    ## 1.2
    # Update patient
    describe "PUT #update patient" do

      let(:patient_attributes) { attributes_for(:patient_for_contact) }

      # Useful variables
      let(:patient_id) { patient_attributes[:patient_id] }
      let(:physio_center_code) { patient_attributes[:physio_center_code] }
      let(:physio_center_id) { PhysioCenter.find_by_code(physio_center_code).id }

      # let! force the method's invocation before each example (not lazy evaluated).
      let!(:patient) { create(:patient, patient_id: patient_id, physio_center_id: physio_center_id) }


      context "with wrong attributes" do

        # invalid attributes with the same :patient_id, :physio_center_code
        let(:invalid_patient_attributes) { attributes_for(:invalid_patient_for_contact, patient_id: patient_id, physio_center_code: physio_center_code) }

        # IT PASSES
        it "respond with 422" do
          put :update, patient: invalid_patient_attributes
          expect(response.status).to eq(422)
        end

        # IT FAILS
        it "doesn't change the attributes of the patient (TO FIX)" do
          put :update, patient: invalid_patient_attributes

          # set variables
          not_updated_patient = Patient.where(patient_id: patient_id, physio_center_id:  physio_center_id).take

          expect(not_updated_patient.attributes).to eq(patient.attributes) #--> FAIL
          # expect(not_updated_patient).to have_attributes(patient.attributes) #--> FAIL
        end
      end
    end
  end
end

控制器

module Api
  module V1
    class PatientsController < ApplicationController

      before_action :set_physio_center, only: [:create, :update]
      before_action :set_patient, only: :update

      def update
        if @patient
          patient_params.extract!(:patient_id, :physio_center_code)
          if @patient.update_attributes(patient_params)
            render json: {message: "Patient updated"}, status: 204
          else
            render json: @patient.errors, status: :unprocessable_entity
          end
        end
      end

      protected

      def set_physio_center
        physio_center_code = params[:patient][:physio_center_code]
        # find_by() doesn't raise exception if record_not_found, so i force it if nil
        @physio_center = PhysioCenter.find_by_code(physio_center_code) ||
            raise(ActiveRecord::RecordNotFound, message: "Couldn't find PhysioCenter with 'physio_center_code'=#{physio_center_code}.\n")
      end

      def set_patient
        patient_id = params[:patient][:patient_id]
        @patient = Patient.find_by(patient_id: patient_id, physio_center_id: @physio_center.id) ||
            raise(ActiveRecord::RecordNotFound, message: "Couldn't find Patient with 'patient_id'=#{patient_id} and 'physio_center_id'=#{@physio_center.id}.\n")
      end

    end
  end
end

工厂

FactoryGirl.define do

  factory :patient_for_contact do

    sequence (:patient_id) { |n| (121+n) }
    birth_date { FFaker::Time.date }
    gender { ["M","F"].sample }
    weight { rand(15.0...120.9).round(1) }
    height { rand(80...220).round(0) }
    bmi { rand(15.0...120.9).round(1) }

    injury_id { Injury.all.ids.sample } # gestisco manualmente
    physio_center_code { (PhysioCenter.all.empty?)? create(:physio_center).code : PhysioCenter.first.code } # Il PhysioCenter non viene creato!
  end

  factory :invalid_patient_for_contact, parent: :patient_for_contact do |f|

    f.gender nil
    f.injury_id nil
  end
end

结果


1) Api::V1::PatientsController with right email and authentication_token PUT #update patient with wrong attributes doesn't change the attributes of the patient
     Failure/Error: expect(not_updated_patient.attributes).to eq(patient.attributes) #--> FAIL

       expected: {"id"=>2, "patient_id"=>123, "physio_center_id"=>2, "birth_date"=>Sun, 09 Jan 2011, "gender"=>"F", "weight"=>25.3, "height"=>105, "bmi"=>22.9, "injury_id"=>8, "created_at"=>Sat, 22 Aug 2015 13:03:29 UTC +00:00, "updated_at"=>Sat, 22 Aug 2015 13:03:29 UTC +00:00}
            got: {"id"=>2, "patient_id"=>123, "physio_center_id"=>2, "birth_date"=>Sun, 09 Jan 2011, "gender"=>"F", "weight"=>25.3, "height"=>105, "bmi"=>22.9, "injury_id"=>8, "created_at"=>Sat, 22 Aug 2015 13:03:30 UTC +00:00, "updated_at"=>Sat, 22 Aug 2015 13:03:30 UTC +00:00}

       (compared using ==)

       Diff:
       @@ -1,6 +1,6 @@
        "bmi" => 22.9,
       -"created_at" => Sat, 22 Aug 2015 13:03:29 UTC +00:00,
       +"created_at" => Sat, 22 Aug 2015 13:03:30 UTC +00:00,
        "gender" => "F",
       @@ -9,6 +9,6 @@
        "physio_center_id" => 2,
       -"updated_at" => Sat, 22 Aug 2015 13:03:29 UTC +00:00,
       +"updated_at" => Sat, 22 Aug 2015 13:03:30 UTC +00:00,
        "weight" => 25.3,

注意:有时 Diff 为空。

created_atupdated_at 的比较似乎有些错误。我不明白为什么会有不同的价值观。 我从数据库中选择相同的资源...

我也试过

expect(not_updated_patient).to have_attributes(patient.attributes)

但它也失败了。

我的开发环境:

  • Ruby 2.2.0
  • Rails 4.2.0
  • FactoryGirl (4.5.0)
  • rspec (3.2.0)
  • rspec-core (3.2.3)
  • rspec 期望 (3.2.1)
  • rspec-rails (3.2.1)
  • DatabaseCleaner (1.4.1)
  • mysql2 (0.3.18)
  • 弹簧 (1.3.6)
  • spring-commands-rspec (1.0.4)

【问题讨论】:

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


    【解决方案1】:

    它们不一样你应该选择一个setoff属性来比较。 updated_atcreated_at 不同。

    也许?

    expect(not_updated_patient.attributes.without('updated_at', 'created_at')).to eq(patient.attributes.without('updated_at', 'created_at'))
    

    使用这个helper

    class Hash
      def without(*keys)
        cpy = self.dup
        keys.each { |key| cpy.delete(key) }
        cpy
      end
    end
    

    【讨论】:

    • 有效!谢谢。我注意到updated_atcreated_at 不同,但我不明白为什么?我从数据库中选择 相同的记录 并且更新操作失败,因此不会更改属性。你有什么想法吗?
    • 对您的回答稍作说明。通过“属性”方法返回的哈希的keys 是字符串类型,而不是符号。所以你必须使用.without("updated_at", "created_at") 引用:apidock.com/rails/v4.2.1/ActiveRecord/AttributeMethods/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-25
    • 1970-01-01
    • 2020-09-20
    • 1970-01-01
    • 2014-03-20
    相关资源
    最近更新 更多