Декрет ActiveRecord не работает в тесте - PullRequest
0 голосов
/ 25 апреля 2019

В своем приложении на Rails 5.1.6 я создал ассоциацию модели Attendance между пользователями и событиями, чтобы пользователи могли участвовать в данном событии.У событий есть целочисленный атрибут seats, который уменьшается каждый раз, когда создается участие.Контроллер посещаемости:

before_action :logged_in_user
before_action :participants_limit, only: :create

def create
  @attendance = current_user.attendances.build(attendance_params)
  if @attendance.save
    @event.decrement(:seats)
    flash[:success] = "Congratulation! Your participation has been recorded."
    redirect_back(fallback_location: root_url)
  else
    flash[:danger] = @event.errors.full_messages.join(', ')
    redirect_back(fallback_location: root_url)
  end
end


private

    def attendance_params
      params.require(:attendance).permit(:event_id)
    end

    def participants_limit
      @event = Event.find(params[:attendance][:event_id])
      if @event.seats == 0
        flash[:danger] = 'Attention! Unfortunately this event is full!'
        redirect_back(fallback_location: root_url)
      end
    end

Я хотел бы протестировать действие создания контроллера Attendance, поэтому я создал следующий тест:

def setup
  @event = events(:event_1)
  @user = users(:user_12)
end

test "should redirect create when participants limit reached" do
  assert @event.participants.count == 2
  assert @event.seats == 5
  participants = (1..5).map do |num|
    users("user_#{num}".to_sym)
  end
  participants.each do |user|
    log_in_as(user)
    post attendances_path, params: { attendance: { user_id: user.id, event_id: @event.id } }
  end
  assert @event.participants.count == 7
  assert @event.seats == 0
  log_in_as(@user)
  assert_no_difference 'Attendance.count' do
    post attendances_path, params: { attendance: { user_id: @user.id, event_id: @event.id } }
  end
  assert_redirected_to root_url
end

Тест не выполнен настрока assert @event.seats == 0: количество мест не уменьшается и результат еще 5: почему?Интересно, почему не работает метод декремента, и если что-то не хватает в тесте.

1 Ответ

1 голос
/ 25 апреля 2019

Ваш @event кэшируется в памяти, и контроллеры изменяют соответствующую запись базы данных.

используют @record.reload.seats в тестах, когда вы ожидаете, что это только что изменилось - это перезагружает запись из базы данных.

Также имейте в виду, что ваш код уязвим для состояния гонки, если два участника попытаются зарегистрироваться одновременно, оберните весь блок кода проверки-изменения в event.with_lock, чтобы смягчить это.

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