SQLite3 :: ConstraintException: невыполненное ограничение UNIQUE не сохраняет объект с ошибками, просто выдает ошибку и останавливает мои тесты - PullRequest
0 голосов
/ 05 октября 2018

Я пытаюсь проверить возвращаемые ошибки при неуникальной попытке создания пользователя в этом 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

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 голосов
/ 05 октября 2018

save возвращает false и заполняет errors, когда запись не была сохранена в базе данных из-за неудачных проверок.В вашем случае нет никаких сбоев проверок, но база данных вызвала исключение.Ошибки такого рода не обрабатываются в вашем коде.

Уникальный индекс в базе данных важен для того, чтобы действительно гарантировать, что в вашей базе данных не будет дубликатов, но вам все равно следует добавить проверку в вашу базу данных.модель для отображения хороших сообщений об ошибках пользователю.

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

Подробнее об этом типе проверки см. в Руководстве по Rails .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...