Ответ 1
Вы можете использовать идиому "rescue nil", чтобы сократить то, что у вас уже есть:
it { expect { eat(what: nil) rescue nil }.not_to change(cat, :status) }
У меня есть метод, который выполняет некоторые действия над моделью Cat, а в случае неправильного ввода вызывает исключение:
context "hungry cat" do
it { expect { eat(what: nil) }.to raise_error }
end
Что я хочу сделать, так это проверить, изменил ли этот метод статус кошек, например:
context "hungry cat" do
it { expect { eat(what: nil) }.to raise_error }
it { expect { eat(what: nil) }.not_to change(cat, :status) }
end
Проблема заключается в том, что, поскольку eat(what: nil)
вызовет исключение, второй it
будет терпеть неудачу, несмотря ни на что. Итак, можно ли игнорировать исключение и проверить какое-то условие?
Я знаю, что можно сделать что-то вроде:
it do
expect do
begin
eat(what: nil)
rescue
end
end.not_to change(cat, :status)
end
Но это слишком уродливо.
Вы можете использовать идиому "rescue nil", чтобы сократить то, что у вас уже есть:
it { expect { eat(what: nil) rescue nil }.not_to change(cat, :status) }
В RSpec 3 вы можете связать два теста с одним. Я считаю, что это более читаемо, чем подход rescue nil
.
it { expect { eat(what: nil) }.to raise_error.and not_to change(cat, :status)}
Вы можете цепочка положительные утверждения с and
. Если вы хотите смешать в отрицательном в цепочке, RSpec 3.1 представил define_negated_matcher
.
Вы можете сделать что-то вроде:
RSpec::Matchers.define_negated_matcher :avoid_changing, :change
expect { eat(what: nil) }
.to raise_error
.and avoid_changing(cat, :status)
Вдохновленный этот комментарий.
Звучит странно, что код eat(what: nil)
не выполняется изолированно для каждого из ваших тестов и влияет на других. Я не уверен, но, возможно, повторная запись тестов немного решит проблему или более точно определит, где проблема (выберите свой вкус ниже).
Использование should
:
context "hungry cat" do
context "when not given anything to eat" do
subject { -> { eat(what: nil) } }
it { should raise_error }
it { should_not change(cat, :status) }
end
end
Использование expect
:
context "hungry cat" do
context "when not given anything to eat" do
let(:eating_nothing) { -> { eat(what: nil) } }
it "raises an error" do
expect(eating_nothing).to raise_error
end
it "doesn't change cat status" do
expect(eating_nothing).to_not change(cat, :status)
end
end
end