2011-05-11 10 views
8

En mi ejemplo simplificado de lo que estoy haciendo realmente, digamos que tengo 2 llamadas a la base de datos:métodos de prueba envueltas en bloques con RSpec

Repo.add(something_stringy) 
Repo.remove(something_floaty) 

y quiero utilizar burla para las llamadas bases de datos, como las llamadas reales se pondrá a prueba en otro lugar:

let(:repo){ 
    repo = double("Repo") 
    repo.should_receive(:add).with(instance_of(String)) 
    repo.should_receive(:remove).with(instance_of(Float)) 
    repo 
} 

before { FakeKlass.const_set :Repo, repo } 

eso es todo lo fino y elegante, pero ahora si me envuelvo las llamadas en una transacción que estoy un poco perplejo:

Repo.transaction do 
    # ... some error checking in here somewhere... 
    Repo.add(something_stringy) 
    Repo.remove(something_floaty) 
end 

porque si escribo una maqueta que recibe transaction que va a recibir la llamada, pero todo en el bloque no se llamará, y me sale:

esperados: 1 vez recibidas: 0 veces

para todos los demás simulacros. ¿Alguien podría mostrarme cómo debería escribir mis especificaciones para lidiar con esto? Intenté leer la página relevante en el libro de RSpec en around(:each), pero para mí era tan claro como el barro.

Cualquier ayuda es muy apreciada.

Respuesta

12

Puede utilizar #and_yield para producir a partir de una cadena de expectativa:

repo.should_receive(:transaction).and_yield 

También no es necesario configurar un doble a apagar métodos en su clase de Repo. Por ejemplo, la configuración se podría escribir:

before(:each) do 
    Repo.should_receive(:transaction).and_yield 
    Repo.should_receive(:add).with(instance_of(String)) 
    Repo.should_receive(:remove).with(instance_of(Float)) 
end 

También podría considerar el uso de stub en lugar de should_receive, ya que no establece expectativas:

before(:each) do 
    Repo.stub(:transaction).and_yield 
    Repo.stub(:add) 
    Repo.stub(:remove) 
end 

En general, sólo se debe utilizar should_receive cuando quieras probar la interacción entre dos objetos. Mi regla personal personal es que si aparece en un before, use stub; si está en un ejemplo, especialmente con un valor específico, use should_receive.

+0

gracias, realmente útil. – iain

+0

gracias, esto también me ayudó a probar el código envuelto Redis.pipelined que estaba actuando de forma similar a la transacción. –

Cuestiones relacionadas