позволять!vs let и раньше в Rspec - PullRequest
0 голосов
/ 04 октября 2018

В Rspec let использует ленивую реализацию, поэтому let(:foo) { create(...) } не инициализируется, пока что-то не вызовет его.Обычно это хорошо, потому что он используется только при необходимости и значительно ускоряет время тестирования rspec.

Иногда, однако, у вас будет спецификация, которая нуждается в этой переменной, но не вызывает ее явно.Так что с ленивым созданием, спецификация потерпит неудачу.

Решение с треском!let!(:foo) { create(...) } заставит переменную инициализироваться.

Некоторые разработчики, похоже, очень против этого и предпочитают:

let(:foo) { create(...) } before do foo end для принудительной инициализации.

Есть ли причина для этого?есть ли разница между этими двумя методами?

Ответы [ 2 ]

0 голосов
/ 09 июля 2019

Многие ситуации - это вопрос стиля, и разработчик не полностью осознает основные функции RSpec, и часто люди просто не имеют смысла.Люди не являются машинами, и, особенно под давлением времени, разработчики делают вещи, которые они не делают в идеальных условиях:).

Но оба представленных случая не являются строго одинаковыми.Например, если вы используете subject, он оценивается в хуке before до инициализации let!, а не внутри it.Я не проверял, но я полагаю, что эти случаи должны показать различия:

let!(:car) { create(:car) }
let(:driver) { create(:driver) }
subject { driver.car() }

it { expect(subject).to eq car } # Fail: 

Это заставляет car быть созданным ранее и доступным для subject:

let(:driver) { create(:driver) }
subject { driver.car() }

before { create(:car) }

it { expect(subject).to eq car } # Success
0 голосов
/ 05 октября 2018

Я могу вспомнить одно отличие: before блоки будут составлять, и вы можете перезаписать let! с помощью let и наоборот.Я приведу вам пример:

context do
  let!(:foo) { create(:foo) }
  let(:bar) { create(:bar) }
  before { bar }

  context do
    # if in this context you wish to switch back to "lazy" versions you can
    # do that for :foo, just do:
    let(:foo) { create(:foo) }
    # but you can't "undo" before, even if you define an empty one:
    before { }
    # it does not cancel the `before` blocks defined in higher contexts
  end
end

Редактировать: Я только что понял, что это на самом деле не отвечает на вопрос, почему кто-то предпочел бы от before до let!.Возможно: как уже упоминалось в комментариях, порядок другой, но если вы зависите от такого нюанса в своих спецификациях - это уже слишком сложно.

...