¿Cómo puedo usar modelos simulados en las especificaciones del controlador AuthLogic?
-
06-07-2019 - |
Pregunta
Estoy tratando de escribir especificaciones para un controlador sin usar accesorios (en lugar de emplear modelos simulados). Este controlador requiere que un usuario inicie sesión, para lo cual estoy empleando AuthLogic , siguiendo el recomendaciones del autor .
describe UsersController do
def mock_user(stubs={})
@mock_user ||= mock_model(User, stubs)
end
context 'when logged in' do
before { activate_authlogic }
it "exposes the logged-in user as @user in response to GET (show)" do
UserSession.create(mock_user)
...
end
...
end
...
end
Todos estos ejemplos fallan en la línea UserSession.create (...)
, informando sobre el efecto de:
Mock 'User_1005' received unexpected message :changed? with (no args)
No estoy seguro de cómo resolver esto; se burla con : cambiado? = > falso
apropiado?
Solución
Iain publicó una solución para usar objetos simulados con AuthLogic . Para reformular, los siguientes ayudantes van a spec_helpers.rb
:
def current_user(stubs = {})
@current_user ||= mock_model(User, stubs)
end
def user_session(stubs = {}, user_stubs = {})
@current_user_session ||= mock_model(UserSession, {:user => current_user(user_stubs)}.merge(stubs))
end
def login(session_stubs = {}, user_stubs = {})
UserSession.stub!(:find).and_return(user_session(session_stubs, user_stubs))
end
def logout
@user_session = nil
end
He incorporado esto a mis especificaciones, y creo que hace exactamente lo que esperaba. Tengo especificaciones de controlador en funcionamiento que exploran modelos simulados para el usuario conectado, por lo que ahora no todos se rompen cuando agrego un campo al Usuario. El ejemplo de Iain de implementar esto en una especificación es como:
describe SecretsController do
before { login }
it "should be very very secret!"
end
P.S. Odio responder mi propia pregunta, pero esta es la respuesta que estaba buscando; Simplemente no lo encontré lo suficientemente temprano.
Otros consejos
Authlogic espera que el registro actúe como una instancia de registro activa. Puede usar una instancia real o un simulacro, pero si usa un simulacro / código auxiliar, debe asegurarse de que responda a todos los métodos requeridos por Authlogic.
Sugeriría usar un objeto de registro activo real en lugar de un simulacro. Si no desea usar un accesorio, puede usar una Fábrica.
La última opción sería pasar un simulacro que responda a cualquier método (puede lograrlo fácilmente mediante method_missing). El problema con esa solución es que no sabe de antemano qué valor debe devolver una llamada a un método específico.
Sí, puede pasar falso pero esto no es realmente una solución. Sería necesario probar / agregar manualmente un valor predeterminado hasta que encuentre que el objeto simulado responde a todas las solicitudes de Authlogic. Pero esto requeriría que siga constantemente authlogic para cualquier cambio interno para reparar las llamadas no respondidas a su código auxiliar.
En Rails 3 esta burla de UserSession ya no funciona, ya que la UserSession de AuthLogic no es una instancia de ActiveRecord :: Base. Solución que funciona para mí:
class UserSession < Authlogic::Session::Base
extend ActiveModel::Naming
end
Encontré que burlarse de los objetos de autlogía eran difíciles y finalmente dejé de burlarme. En cambio, ahora uso un enfoque de generadores usando object daddy . Mis pruebas funcionales son mucho más felices ahora. Por cierto, debería ser + object_daddy absolutamente rocas. Los contextos transaccionales de Shoulda aseguran que mi base de datos de prueba permanezca limpia y no tengo que burlarme de objetos simples de registro activo en primer lugar.