RSpec: Как написать тестовый блок для получения исключения, которое вызывается в приватном методе - PullRequest
0 голосов
/ 04 октября 2018

Я реализовал Оптимистическую блокировку для состояния гонки.Для этого я добавил дополнительный столбец lock_version в Product.Метод: recalculate вызывает private method_1, затем сохраняет (save!) продукт.Я не могу использовать save! в частном порядке method_1, потому что другие вещи не удастся.Я не хочу перестраивать бизнес-логику.

#Product: Model's new field:
    #  lock_version                       :integer(4)      default(0), not null

def recalculate
  method_1
  self.save!
end

private
def method_1
    begin
      ####
      ####
      if self.lock_version == Product.find(self.id).lock_version
         Product.where(:id => self.id).update_all(attributes)
      else
         raise ActiveRecord::StaleObjectError.new(self, "test")
      end
    rescue ActiveRecord::StaleObjectError => e
        if tries < 3
           tries += 1
           sleep(1 + tries)
           self.reload
           retry
        else
           raise Exception.new(timeout.inspect)
        end
    end
end

Контрольный пример Rspec:

  it 'if car is updated then ActiveRecord::StaleObjectError should be raised' do
    prod_v1 =Product.find(@prod.id)
    prod_v2 = Car.find(@prod.id)
    prod_v1.recalculate
    prod_v1.reload  # will make lock_version of prod_v1 to 1

    prod_v2.recalculate # howvever lock_version of prod_v2 is still 0.

    expect(car_v2).to receive(:method1).and_raise(ActiveRecord::StaleObjectError)
  end

Когда я пытаюсь написать над контрольным примером, он должен вызвать исключение ActiveRecord::StaleObjectError.Тем не менее, я получаю сообщение об ошибке типа

 Failure/Error: expect(car_v2).to receive(:set_total_and_buckets_used).and_raise(ActiveRecord::StaleObjectError)
 ArgumentError:
   wrong number of arguments (0 for 2)

1 Ответ

0 голосов
/ 04 октября 2018

Вы можете написать что-то вроде:

expect(ActiveRecord::StaleObjectError).to receive(:new).and_call_original

Поскольку вы спасаете исключение

Убедитесь, что отметили https://relishapp.com/rspec/rspec-expectations/docs/built-in-matchers

expect(car_v2).to receive(:method1).and_raise(ActiveRecord::StaleObjectError)

Означает, чтокогда car_v2 получает method1, вы не будете его вызывать, но вызовете исключение типа ActiveRecord::StaleObjectError.Вот почему вы также получаете ArgumentError

С помощью rspec вы можете проверить, что определенный код вызывает ошибку (которая не обрабатывается в вашем случае, она обрабатывается -> rescue ...) следующим образом:

expect { my_cool_method }.to raise_error(ErrorClass)
...