2009-03-20 14 views
11

Quiero llamar a un named_scope que sólo devolverá un registro, pero el named_scope devuelve una matriz, que no es un gran problema ya que sólo puede encadenar con .First:Stubbing Métodos en cadena con Rspec

Model.named_scope(param).first 

y esto funciona, con lo que estoy luchando es cómo rescindir el llamado encadenado. ¿Alguien tiene una referencia o una respuesta sobre cómo lograr esto con la burla de Rspec?

Respuesta

16

Me di cuenta de algo.

Client.stub!(:named_scope).and_return(@clients = mock([Client])) 
@clients.stub!(:first).and_return(@client = mock(Client)) 

que me permite llamar a mi controlador:

@client = Client.named_scope(param).first 

Funciona, pero ¿hay una solución mejor?

EDIT:

La liberación de rspec 1.2.6 nos permite utilizar stub_chain lo que significa que ahora puede ser:

Client.stub_chain(:named_scope, :chained_call).and_return(@clients = [mock(Client)]) 

Ésta era la parte superior de la cabeza, como siempre comprobar la API para obtener información específica:)

+2

Tal vez mover la sección EDIT: a la parte superior de la respuesta – Sam

+0

Muchas gracias, Chris! ¡Ayudó mucho! – ep3static

1

Supongo que esto está en una especificación de controlador?

Su propia sugerencia debería funcionar bien. Otra posibilidad es mover la llamada named_scope dentro de su modelo, para evitar el problema por completo. Esto también estaría en línea con el consejo de "modelos gordos, controladores delgados".

0

Creo que ya ha hecho la cosa del controlador delgado colocando la consulta en un ámbito con nombre donde se puede reutilizar. Aquí hay un código que utilicé antes de comenzar a usar ámbitos con nombre.

def mock_comm(stubs={}) 
    @mock_comm ||= mock_model(Comm, stubs) 
    end 

    describe "responding to GET index" do 

    it "should expose all comms as @comms" do 
     Comm.should_receive(:find).with(:all).and_return([mock_comm]) 
     get :index 
     assigns[:comms].should == [mock_comm] 
    end 
# ... 

que probablemente escribir código muy similar a lo que ya tiene, pero tal vez lo puso en un ayudante que me permite reutilizarlo. La otra cosa es usar un marco de burla diferente que tal vez te dé más control. Echa un vistazo a las críticas de Ryan Bates en RSpec: ahora es un poco viejo, pero aún hay algunas buenas ideas ahí.

2

mejor versión de

Client.stub!(:named_scope).and_return(@clients = mock([Client])) 
@clients.stub!(:first).and_return(@client = mock(Client)) 

será:

Client.should_receive(:named_scope).with(param).and_return do 
    record = mock_model(Comm) 
    record.should_receive(:do_something_else) 
    [record] 
end 
2

La pregunta es bastante viejo y por lo tanto hay pocas mejoras en la forma en que se puede hacer tropezar. Ahora puede usar el método stub_chain para encontrar una cadena de llamadas a métodos. Por ejemplo:

@client = Client.named_scope(param).first

puede apagó con:

Client.stub_chain(:named_scope,:first).and_return(@client = mock(Client))

Más ejemplos de stub_chaining:

describe "stubbing a chain of methods" do 
    subject { Object.new } 

    context "given symbols representing methods" do 
    it "returns the correct value" do 
     subject.stub_chain(:one, :two, :three).and_return(:four) 
     subject.one.two.three.should eq(:four) 
    end 
    end 

    context "given a string of methods separated by dots" do 
    it "returns the correct value" do 
     subject.stub_chain("one.two.three").and_return(:four) 
     subject.one.two.three.should eq(:four) 
    end 
    end 
end 

or please have a look at:

Larga vida a las rspecs !!! :)