RSpec: ¿cómo probar si se llamó a un método?

112

Cuando escribo pruebas de RSpec, me encuentro escribiendo una gran cantidad de código que se ve así para asegurarme de que se llamó a un método durante la ejecución de una prueba (por el bien del argumento, digamos que realmente no puedo interrogar el estado del objeto después de la llamada porque la operación que realiza el método no es fácil de ver el efecto de).

describe "#foo"
  it "should call 'bar' with appropriate arguments" do
    called_bar = false
    subject.stub(:bar).with("an argument I want") { called_bar = true }
    subject.foo
    expect(called_bar).to be_true
  end
end

Lo que quiero saber es: ¿Existe una sintaxis mejor disponible que esta? ¿Me estoy perdiendo algo de genialidad de RSpec funky que reduciría el código anterior a unas pocas líneas? should_receiveParece que debería hacer esto, pero leyendo más, parece que no es exactamente lo que hace.

Mikey Hogarth
fuente
3
Consulte aquí: stackoverflow.com/questions/1328277/…
kddeisz
@Peter Alfvin El OP pedía sintaxis activada should_receive, así que pensé que esa pregunta ayudaría.
kddeisz

Respuestas:

141
it "should call 'bar' with appropriate arguments" do
  expect(subject).to receive(:bar).with("an argument I want")
  subject.foo
end
loco
fuente
1
Lo siento, no entiendo cómo este formato de "to .. receive (: bar)" comprueba el valor de "called_bar" en este ejemplo. ¿Puedes explicarme eso?
ecoding5
2
@ ecoding5 no. No es así y tampoco debería comprobarse called_bar. Eso fue solo una bandera para garantizar que se llamara al método, pero expect(...).to receive(...)ya lo está cubriendo. Es más claro y semántico
wacko
@wacko oooh, lo tengo, gracias por aclarar eso. No lo vi la primera vez.
ecoding5
102

En la nueva rspec expectsintaxis, esto sería:

expect(subject).to receive(:bar).with("an argument I want")
Uri Agassi
fuente
37

Lo siguiente debería funcionar

describe "#foo"
  it "should call 'bar' with appropriate arguments" do
     subject.stub(:bar)
     subject.foo
     expect(subject).to have_received(:bar).with("Invalid number of arguments")
  end
end

Documentación: https://github.com/rspec/rspec-mocks#expecting-arguments

bjhaid
fuente
Gracias. Estaba recibiendo "NoMethodError" has_received? - Creo que esto podría tener que ver con las versiones de rspec. Encontré otra solución que funcionó para mí (la marcada como correcta arriba)
Mikey Hogarth
@MikeyHogarth Esta respuesta sugirió have_received(el enfoque de "espías" después del hecho), no has_received, que no es parte de ninguna versión de RSpec que yo sepa.
Peter Alfvin
2

Para cumplir completamente con la sintaxis RSpec ~> 3.1 y rubocop-rspecla opción predeterminada para la regla RSpec/MessageSpies, esto es lo que puede hacer con spy:

Las expectativas de mensajes ponen la expectativa de un ejemplo al principio, antes de invocar el código en prueba. Muchos desarrolladores prefieren utilizar un patrón organizar-actuar-afirmar (o dar-cuando-entonces) para estructurar las pruebas. Los espías son un tipo alternativo de doble de prueba que respalda este patrón al permitirle esperar que se haya recibido un mensaje después del hecho, utilizando have_received.

# arrange.
invitation = spy('invitation')

# act.
invitation.deliver("[email protected]")

# assert.
expect(invitation).to have_received(:deliver).with("[email protected]")

Si no usa rubocop-rspec o usa una opción no predeterminada. Por supuesto, puede usar RSpec 3 predeterminado con expectativa.

dbl = double("Some Collaborator")
expect(dbl).to receive(:foo).with("[email protected]")
Yi Zeng
fuente