with tutorial tests test run rails how example effective better ruby unit-testing testing rspec

ruby - tutorial - ¿Cómo ''espero'' algo que provoque una excepción en RSpec?



rspec test example (4)

Tengo un método que realiza algunas acciones en el modelo de Cat y en el caso de una entrada incorrecta se genera una excepción:

context "hungry cat" do it { expect { eat(what: nil) }.to raise_error } end

Lo que quiero hacer es verificar si este método cambia el estado de los gatos, así:

context "hungry cat" do it { expect { eat(what: nil) }.to raise_error } it { expect { eat(what: nil) }.not_to change(cat, :status) } end

El problema es que, como eat(what: nil) generará una excepción, la segunda fallará sin importar qué. Entonces, ¿es posible ignorar la excepción y verificar alguna condición?

Sé que es posible hacer algo como:

it do expect do begin eat(what: nil) rescue end end.not_to change(cat, :status) end

Pero es demasiado feo.


Suena extraño que el código eat(what: nil) no se ejecute de forma aislada para cada una de sus pruebas y afecte a las demás. No estoy seguro, pero quizás reescribir las pruebas levemente resolverá el problema o identificará con más precisión dónde está el problema (seleccione su sabor a continuación).

El uso 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

Usando 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''s status" do expect(eating_nothing).to_not change(cat, :status) end end end


Puede usar el modismo "rescatar nada" para acortar lo que ya tiene:

it { expect { eat(what: nil) rescue nil }.not_to change(cat, :status) }


En RSpec 3 puede encadenar las dos pruebas en una sola. Encuentro esto más legible que el enfoque de rescue nil .

it { expect { eat(what: nil) }.to raise_error.and not_to change(cat, :status)}


Puede encadenar afirmaciones positivas con and . Si desea mezclar uno negado en la cadena, RSpec 3.1 introdujo define_negated_matcher .

Podrías hacer algo como:

RSpec::Matchers.define_negated_matcher :avoid_changing, :change expect { eat(what: nil) } .to raise_error .and avoid_changing(cat, :status)

Inspirado por este comentario .