我编写了一个简单的规范,用无效属性测试更新操作。我希望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_at
和updated_at
比较中存在一些错误。我不明白为什么会有不同的价值观。
我从DB中选择相同的资源......
我也试过
expect(not_updated_patient).to have_attributes(patient.attributes)
但它也失败了。
我的发展环境:
答案 0 :(得分:0)
它们与您应该选择要比较的抵消属性不同。 updated_at
和created_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