rails matchers bot ruby-on-rails-3 rspec

ruby on rails 3 - matchers - RSpec Newbie: "Actualizar atributos=> falso" no se reconoce



rspec rails 5 (1)

Justo comenzando con RSpec. Todo va bien, a excepción de una especificación con controladores anidados.

Estoy tratando de asegurar que cuando un recurso de ''comentario'' (anidado bajo ''publicación'') se actualice con parámetros no válidos, presente la plantilla ''editar''. Estoy luchando para conseguir que rspec reconozca el activador: update_attributes => false. Si alguien tiene alguna sugerencia, sería muy apreciada. Intento de código a continuación:

def mock_comment(stubs={}) stubs[:post] = return_post stubs[:user] = return_user @mock_comment ||= mock_model(Comment, stubs).as_null_object end describe "with invalid paramters" dog it "re-renders the ''edit'' template" do Comment.stub(:find).with("12") { mock_comment(:update_attributes => false) } put :update, :post_id => mock_comment.post.id, :id => "12" response.should render_template("edit") end end

Y el controlador:

def update @comment = Comment.find(params[:id]) respond_to do |format| if @comment.update_attributes(params[:comment]) flash[:notice] = ''Post successfully updated'' format.html { redirect_to(@comment.post) } format.xml { head :ok } else format.html { render :action => "edit" } format.xml { render :xml => @comment.errors, :status => :unprocessable_entity } end end end

Y finalmente, el error:

Failure/Error: response.should render_template("edit") expecting <"edit"> but rendering with <"">. Expected block to return true value.


Este es un problema bastante interesante. Una solución rápida es simplemente reemplazar la forma de bloque de Comment.stub :

Comment.stub(:find).with("12") { mock_comment(:update_attributes => false) }

con un and_return explícito:

Comment.stub(:find).with("12")./ and_return(mock_comment(:update_attributes => false))

En cuanto a por qué estas dos formas deben producir resultados diferentes, eso es un poco de un rasguño de cabeza. Si juegas con la primera forma, verás que el simulacro está regresando self lugar de false cuando se llama al método stubbed. Eso nos dice que no ha rechazado el método (ya que está especificado como un objeto nulo).

La respuesta es que al pasar en un bloque, el bloque solo se ejecuta cuando se llama al método stubbed, no cuando se define el stub. Entonces cuando usa el formulario de bloque, la siguiente llamada:

put :update, :post_id => mock_comment.post.id, :id => "12"

está ejecutando mock_comment por primera vez. Dado que :update_attributes => false no se transfiere, el método no se repite y se devuelve el simulacro en lugar de false . Cuando el bloque invoca mock_comment , devuelve @mock_comment , que no tiene el stub.

Por el contrario, usar la forma explícita de and_return invoca mock_comment inmediatamente. Probablemente sería mejor usar la variable de instancia en lugar de llamar al método cada vez para aclarar el intento:

it "re-renders the ''edit'' template" do mock_comment(:update_attributes => false) Comment.stub(:find).with("12") { @mock_comment } put :update, :post_id => @mock_comment.post.id, :id => "12" response.should render_template("edit") end