2010-10-30 24 views
14

Estoy tratando de probar un alcance que tengo que se basa en una cadena de otros ámbitos. ("public_stream" a continuación).Stubbing Chained Queries in Rails 3 y Rspec

scope :public, where("entries.privacy = 'public'") 
scope :completed, where("entries.observation <> '' AND entries.application <> ''") 
scope :without_user, lambda { |user| where("entries.user_id <> ?", user.id) } 
scope :public_stream, lambda { |user| public.completed.without_user(user).limit(15) } 

Usando una prueba como esta:

it "should use the public, without_user, completed, and limit scopes" do 
     @chain = mock(ActiveRecord::Relation) 
     Entry.should_receive(:public).and_return(@chain) 
     @chain.should_receive(:without_user).with(@user).and_return(@chain) 
     @chain.should_receive(:completed).and_return(@chain) 
     @chain.should_receive(:limit).with(15).and_return(Factory(:entry)) 

     Entry.public_stream(@user) 
    end 

Sin embargo, sigue recibiendo este error:

Failure/Error: Entry.public_stream(@user) 
undefined method `includes_values' for #<Entry:0xd7b7c0> 

Parece includes_values ​​es una variable de instancia del objeto ActiveRecord :: Relation , pero cuando intento resguardarlo, sigo recibiendo el mismo error. Me preguntaba si alguien tenía experiencia con el corte de las nuevas consultas encadenadas de Rails 3. Puedo encontrar un montón de discusión sobre hash find de 2.x, pero nada sobre cómo probar lo que está actualizado.

+1

Por curiosidad, ¿funciona si no se utiliza 'public'?Hay un conflicto entre el nombre del alcance y la palabra clave Ruby 'public'. No estoy seguro de que ese sea el problema, pero estaría interesado en qué parte de la cadena falla esta prueba. –

+0

Los ámbitos están directamente relacionados con la base de datos, por lo que no tiene sentido probarlos de forma aislada. Simplemente crea algunos registros reales y prueba qué devuelve la consulta. – RocketR

Respuesta

20

utilizo rspec de stub_chain para esto. Es posible que pueda usar algo como:

some_model.rb

scope :uninteresting, :conditions => ["category = 'bad'"], 
         :order => "created_at DESC" 

controlador

@some_models = SomeModel.uninteresting.where(:something_else => true) 

especificación

SomeModel.stub_chain(:uninteresting, :where) {mock_some_model} 
0

Intente pasar el Arel, ya que podría ser el caso de que faltan telescopios.

it "should use the public, without_user, completed, and limit scopes" do 
    @chain = Entry 
    @chain.should_receive(:public).and_return(@chain.public) 
    @chain.should_receive(:without_user).with(@user).and_return(@chain.without_user(@user)) 
    @chain.should_receive(:completed).and_return(@chain.completed) 
    @chain.should_receive(:limit).with(15).and_return(Factory(:entry)) 

    Entry.public_stream(@user) 
end 
1

En primer lugar, es probable que no debería estar probando incorporado en la funcionalidad Rails.

You should only be writing unit tests for code that you have written yourself (which should be second-nature if you practice TDD) – Rails ships with its own comprehensive suite of unit tests for its built-functionality – there is no point in replicating this.

En lo que se genera el error, creo que el problema es en esta línea:

@chain.should_receive(:limit).with(15).and_return(Factory(:entry)) 

usted está esperando la cadena para devolver un Factory, lo que efectivamente ser una instancia de ActiveRecord , pero en realidad every relation returns yet another ActiveRecord::Relation.

Por lo tanto, su expectativa en sí misma es incorrecta y, de hecho, puede estar causando el error que se está produciendo.

Tenga en cuenta que los ámbitos en realidad no devuelven los registros que espera, hasta que explícitamente iterar sobre ellos. Además, los registros de la relación nunca devuelven un solo registro. Ellos siempre devuelven una matriz vacía o una matriz con registros.