IIC3745-2020-2 / syllabus

Repositorio principal para el curso Testing 2020-2
16 stars 2 forks source link

Problema Test Controlador #44

Closed jcechavarri closed 4 years ago

jcechavarri commented 4 years ago

Hola!

Estoy teniendo un problema al testear el controlador de usuario, en específico el update. El test es:

image

Y el error

image

Me imagino que estoy pasando mal los parámetros pero no entiendo bien como debería ser 😢

Muchas gracias!

Hernan4444 commented 4 years ago

Hola,

Creo que podría faltar el render_views dentro del describe Fuente: https://stackoverflow.com/questions/24653543/expecting-index-but-rendering-with

Por otro lado, podrías hacer push del código en caso de no serlo, así podemos ver bien el controlador y todo el código para ayudar mejor

Saludos :v:

rasaffie commented 4 years ago

Sin revisar en detalle tu sintaxis, hay algo extraño en tu test: no puedes esperar que haga render de show al mismo tiempo que se espera un redirect.

Normalmente una acción exitosa de update hace un redirect a la acción show, por lo que eso podría explicar que no se esté haciendo render del show (que es lo que dice tu mensaje de error). Por otra parte, una acción fallida de update hace render de edit (no show), para mostrar el formulario con los errores correspondientes. Para probar ambos flujos debes realizar 2 tests distintos.

Por último, como dice @Hernan4444, falta ver el código de tu aplicación para entender bien qué se está ejecutando. Sin embargo, más de un archivo puede afectar este comportamiento, por lo que debes tener claro el flujo completo que atraviesa una request en tu aplicación. De todas formas, render_views no es el problema: está opción lo que hace es que se "dibujen" las vistas realmente, para así probar su contenido real. Lo que valida render_template es que se llame al template, pero no el contenido mismo del template porque este por defecto no se escribe, para así ahorrar tiempo de ejecución de los tests.

jcechavarri commented 4 years ago

@rasaffie @Hernan4444

Entiendo que deben ser 2 tests (acción exitosa y fallida) pero no me queda claro como testear eso (pensé que si mis parámetros eran correctos me redireccionaría al show). Además, si le paso parámetros erróneos (nombre vacío, contraseñas incorrectas) igual se hace el update al atributo. Al pasar esto significa que tampoco voy a poder testear el update fallido ya que siempre se acepta mi update.

Bajo esta misma línea, ¿Cómo puedo testear que además de responder con redirección llame a la vista correspondiente?

Dejo acá el link al test específico en nuestro repositorio.

Gracias de nuevo!

Hernan4444 commented 4 years ago

Hola, sobre esta pregunta:

Bajo esta misma línea, ¿Cómo puedo testear que además de responder con redirección llame a la vista correspondiente?

Una opción es hacer 2 test: uno done valida que se redireccione a la vista que quiere (por ejemplo expect(response).to redirect_to user_path(user.id) ) y otro test donde cargue esa vista y revisa que el template es el esperado. Pero lo que pides se puede hacer con otro tipo de tests más de integración, no en los unitarios para controladores. Sobre ese último tema, el profesor lo detallará mejor el fin de semana.

Saludos :v:

jcechavarri commented 4 years ago

@Hernan4444

Gracias!

Todavía me queda la duda sobre el

si le paso parámetros erróneos (nombre vacío, contraseñas incorrectas) igual se hace el update al atributo.

He intentado de varias formas y todavía no logro cubrir la parte del controlador que maneja los updates fallidos.

rasaffie commented 4 years ago

Hola Juan Carlos,

Sobre tu última pregunta, en tu controlador de users tu método user_params se ve así:

def user_params
  params.require(:user).permit(:name, :last_name)
end

Por esta razón los únicos parámetros que se están considerando al realizar @user.update(user_params) son name y last_name. Puedes leer más sobre esto en la guía oficial de Rails sobre Strong Parameters.

Además, en tu test definiste tus parámetros como:

params = { 
  "name"=>"new_name",
  "last_name"=>user.last_name,
  "email"=>user.email,
  "password"=>"newpassw",
  "password_confirmation"=>"newpassw",
  "current_password"=>user.password
}

los cuales no están dentro de un objeto user como lo definen tus user_params. Por otra parte, utilizas la notación implicita de RSpec is_expected.to que infiere el subject, pero por como organizaste tus tests lo debe estar haciendo de mala manera. Te recomiendo que definas un subject explícitamente o que llames a la acción directamente como en tu test de destroy:

expect { delete :destroy, params: { id: user } }.to change { User.count }.by(-1)

Cuéntame si aún tienes dudas, saludos,