tutorial mvc formulario form example español ejemplo docs spring spring-mvc

formulario - spring mvc pdf



Unidad probando un método dependiente del contexto de solicitud (4)

Estoy escribiendo una prueba unitaria para un método que contiene la siguiente línea:

String sessionId = RequestContextHolder.currentRequestAttributes().getSessionId();

Obtuve el siguiente error:

java.lang.IllegalStateException: no se ha encontrado ninguna solicitud enlazada a hilos: ¿se refiere a atributos de solicitud fuera de una solicitud web real, o procesando una solicitud fuera del hilo receptor original? Si en realidad está operando dentro de una solicitud web y aún recibe este mensaje, su código probablemente se esté ejecutando fuera de DispatcherServlet / DispatcherPortlet: en este caso, use RequestContextListener o RequestContextFilter para exponer la solicitud actual.

La razón es bastante obvia: no estoy ejecutando la prueba en un contexto de solicitud.

La pregunta es, ¿cómo puedo probar un método que contiene una llamada a un método dependiente del contexto de solicitud en un entorno de prueba?

Muchas gracias.



Si el método contiene:

String sessionId = RequestContextHolder.currentRequestAttributes().getSessionId();

es el método del controlador web, entonces recomendaría cambiar la firma del método, para que usted / spring pase la solicitud como un separador separado al método.

Luego puede eliminar la parte problemática String RequestContextHolder.currentRequestAttributes() y usar HttpSession direcly.

Entonces debería ser muy fácil usar un objeto Session ( MockHttpSession ) MockHttpSession en la prueba.

@RequestMapping... public ModelAndView(... HttpSession session) { String id = session.getId(); ... }


Spring-test tiene un simulacro de solicitud flexible llamado MockHttpServletRequest.

MockHttpServletRequest request = new MockHttpServletRequest(); RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request));


Suponiendo que su clase es algo así como:

class ClassToTest { public void doSomething() { String sessionId = RequestContextHolder.currentRequestAttributes().getSessionId(); // Do something with sessionId } }

Si no tiene la capacidad de cambiar la clase que usa RequestContextHolder , puede anular la clase RequestContextHolder en su código de prueba. Es decir, crea una clase con el mismo nombre, en el mismo paquete, y asegúrese de que esté cargada antes de la clase Spring real.

package org.springframework.web.context.request; public class RequestContextHolder { static RequestAttributes currentRequestAttributes() { return new MyRequestAttributes(); } static class MyRequestAttributes implements RequestAttributes { public String getSessionId() { return "stub session id"; } // Stub out the other methods. } }

Ahora, cuando se ejecuten las pruebas, recogerán su clase RequestContextHolder y la usarán con preferencia a la de Spring (suponiendo que classpath esté configurado para que esto suceda). Esta no es una buena manera particular de hacer que sus pruebas se ejecuten, pero podría ser necesario si no puede cambiar la clase que está probando.

Alternativamente, podría ocultar la recuperación de la identificación de la sesión detrás de una abstracción. Por ejemplo, introduce una interfaz:

public interface SessionIdAccessor { public String getSessionId(); }

Crear una implementación:

public class RequestContextHolderSessionIdAccessor implements SessionIdAccessor { public String getSessionId() { return RequestContextHolder.currentRequestAttributes().getSessionId(); } }

Y usa la abstracción en tu clase:

class ClassToTest { SessionIdAccessor sessionIdAccessor; public ClassToTest(SessionIdAccessor sessionIdAccessor) { this.sessionIdAccessor = sessionIdAccessor; } public void doSomething() { String sessionId = sessionIdAccessor.getSessionId(); // Do something with sessionId } }

Luego puede proporcionar una implementación ficticia para sus pruebas:

public class DummySessionIdAccessor implements SessionIdAccessor { public String getSessionId() { return "dummy session id"; } }

Este tipo de cosas resalta una de las mejores prácticas habituales para ocultar ciertos detalles medioambientales detrás de las abstracciones para que pueda cambiarlas si cambia su entorno. Esto se aplica igualmente a hacer que sus pruebas sean menos frágiles al intercambiar las implementaciones ficticias por las "reales".