ruby-on-rails - SQLite3::ConstraintException: UNIQUE constraint failed 不是保存有错误的对象,只是抛出一个错误并停止我的测试
问题描述
我正在尝试测试在此 API 中创建用户的非唯一尝试返回的错误。
RSpec.describe 'POST /signup', type: :request do
let(:url) { '/signup' }
let(:params) do
{
user: {
email: 'user@example.com',
password: 'password'
}
}
end
context 'when user is unauthenticated' do
before { post url, params: params }
it 'returns 200' do
expect(response.status).to eq 200
end
it 'returns a new user' do
expect(response).to match_response_schema('user')
end
end
context 'when user already exists' do
before do
Fabricate :user, email: params[:user][:email]
post url, params: params
end
it 'returns bad request status' do
expect(response.status).to eq 400
end
it 'returns validation errors' do
expect(json['errors'].first['title']).to eq('Bad Request')
end
end
结尾
以上是我的规范文件。以下是引发错误的注册文件:
class RegistrationsController < Devise::RegistrationsController
respond_to :json
def create
build_resource(sign_up_params)
resource.save
render_resource(resource)
end
end
我得到的错误:
3) POST /signup when user already exists returns validation errors
Failure/Error: resource.save
ActiveRecord::RecordNotUnique:
SQLite3::ConstraintException: UNIQUE constraint failed: users.email:
INSERT INTO "users" ("email", "encrypted_password") VALUES (?, ?)
我知道它会抛出该错误,这就是我在应用程序控制器中定义以下内容以返回格式正确的错误的原因:
class ApplicationController < ActionController::API
def render_resource(resource)
if resource.errors.empty?
render json: resource
else
validation_error(resource)
end
end
def validation_error(resource)
render json: {
errors: [
{
status: '400',
title: 'Bad Request',
detail: resource.errors,
code: '100'
}
]
}, status: :bad_request
end
end
目标是如果resource.save
不保存或抛出错误,该render_resource
函数将返回 JSON 格式的错误。但是,每次它命中resource.save
它都会在我的测试中引发错误并停止其余的测试。任何帮助将不胜感激!
解决方案
save
当由于验证失败而没有将记录保存到数据库时返回false
并填充。errors
在您的情况下,没有任何验证失败,但数据库引发了异常。您的代码中不会处理这些类型的错误。
数据库中的唯一索引对于真正确保您不会在数据库中出现重复非常重要,但您仍然应该向模型添加验证以向用户显示漂亮的错误消息。
# add to app/models/user.rb
validates :email, uniqueness: { case_sensitive: false }
在 Rails 指南中阅读有关此类验证的更多信息。
推荐阅读
- ios - 如何打印 XCUITest 中的所有静态文本
- f# - 如何使用 HTTPS 协议使用 Suave 启动 Web 服务器?
- apache-spark - 如何在 Scala 中将 Spark DataFrames 一一添加到 Seq()
- java - @Size 注释似乎不适用于我的班级
- c# - 将具有通用和具体实现的存储库注入控制器
- android-gradle-plugin - android-annotation:错误:找不到符号
- javascript - 如何将axios响应数据设置为变量
- python - 如何在信号图中对对应于同一山丘的峰值点进行分组
- typescript - Jest 和 Typescript - 在函数中模拟 const
- python - 拆分数据框列中的值