SQLite3 :: ConstraintException:唯一约束失败不保存带有错误的对象,只是抛出错误并停止我的测试

时间:2018-10-05 14:42:06

标签: ruby-on-rails ruby api activerecord

我正在尝试通过非唯一尝试在此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时,都会在我的测试中引发错误并停止其余的测试。任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:1)

当由于验证失败而未将记录保存到数据库时,

save返回false并填充errors。在您的情况下,不会失败任何验证,但是数据库会引发异常。这些错误不会在您的代码中处理。

数据库中的唯一索引对于真正确保您不会在数据库中出现重复项很重要,但是您仍然应该在模型中添加验证以向用户显示漂亮的错误消息。

# add to app/models/user.rb
validates :email, uniqueness: { case_sensitive: false }

详细了解此类validation in the Rails Guides