java - pruebas - spring boot unit test rest controller
Pruebas unitarias vs pruebas de integraciĆ³n con Spring (7)
Algunos puntos aislados:
Sí, es un enfoque común para las pruebas de Spring: pruebas unitarias separadas y pruebas de integración donde el primero no carga ningún contexto de Spring.
Para las pruebas de su unidad, tal vez considere la burla para asegurarse de que sus pruebas se centren en un módulo aislado.
Si sus pruebas están conectadas en un montón de dependencias, entonces no son realmente pruebas unitarias. Son pruebas de integración en las que está cableando dependencias que usan inyección nueva en lugar de dependencia. ¡Una pérdida de tiempo y esfuerzo duplicado cuando su aplicación de producción utiliza Spring!
Las pruebas de integración básicas para mostrar los contextos de Spring son útiles.
La anotación @required puede ayudarlo a asegurarse de que detecta las dependencias requeridas en su cableado de Spring.
Tal vez busque en Maven, que le dará fases explícitas para vincular su unidad y las pruebas de integración. Maven es ampliamente utilizado en la comunidad de Spring.
Estoy trabajando en un proyecto Spring MVC, y tengo pruebas unitarias para todos los componentes en el árbol fuente.
Por ejemplo, si tengo un controlador HomeController
, que necesita tener un LoginService
inyectado en él, entonces en mi prueba de unidad HomeControllerTest
simplemente HomeControllerTest
el objeto como normal (fuera de Spring) e inyecto la propiedad:
protected void setUp() throws Exception {
super.setUp();
//...
controller = new HomeController();
controller.setLoginService( new SimpleLoginService() );
//...
}
Esto funciona muy bien para probar cada componente como una unidad aislada, excepto que ahora tengo unas pocas docenas de clases en el proyecto, después de escribir una clase y escribir una prueba de unidad exitosa para ello, me olvido de actualizar mi archivo de contexto Spring MVC que sí lo hace el cableado real en la aplicación desplegada. Descubrí que olvidé actualizar el archivo de contexto cuando implementé el proyecto en Tomcat y encontré un montón de NullPointers de beans no conectados.
Asi que aqui están mis preguntas:
Este es mi primer proyecto de Spring: ¿es normal crear pruebas unitarias para los beans individuales, como lo he hecho, y luego crear un segundo conjunto de pruebas (pruebas de integración) para probar que todo funciona como se espera con el contexto de la aplicación real? ¿Existe una mejor práctica establecida para esto?
Además, ¿cómo separe las pruebas unitarias de las pruebas de integración? Tengo todo el código fuente en
src
, la unidad prueba entest
: ¿debería haber una segunda carpeta de prueba (comotest-integration
) para los casos de prueba de integración?
Como este es mi primer proyecto de primavera, tengo curiosidad de cómo otros suelen hacer este tipo de cosas, y en lugar de reinventar la rueda, prefiero preguntar al resto de la comunidad.
Con respecto a ejecutar las pruebas unitarias por separado de las pruebas de integración, puse todo lo último en un directorio de prueba de integración y los ejecuté usando IDE / Ant usando un enfoque como this . Funciona para mi.
Cuando creé pruebas de integración para aplicaciones web, las puse en un directorio aparte. Se crean utilizando jUnit o TestNG e interactúan con el sistema bajo prueba utilizando algo como Selenium que llega a las páginas web como si fueran usuarios. El ciclo sería así: compilar, ejecutar pruebas unitarias, crear la aplicación web, implementarla en un servidor en ejecución, ejecutar las pruebas, anular la implementación de la aplicación e informar los resultados. La idea es probar todo el sistema.
Gran parte de la tediosa contabilidad doble con resorte desaparece si también cambia a un régimen puramente anotado, donde anota todos sus beans con @Component, @Controller, @Service y @Repository. Simplemente agregue @Autowired a los atributos que necesita para ser inyectado.
Consulte la sección 3.11 del manual de referencia de la primavera. http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-annotation-config
En una nota relacionada, hemos estado usando las pruebas de unidad / Integratrion de división que describe KenG. En mi régimen más reciente, también presentamos una tercera "clase" de pruebas, "ComponentTests". Funcionan con cableado completo de muelles, pero con implementaciones de stub cableadas (utilizando filtros de componentes y anotaciones en primavera).
La razón por la que hicimos esto fue porque para la capa de "servicio" terminas con una horrenda cantidad de lógica de cableado manual para cablear manualmente el grano, y algunas veces cantidades ridículas de objetos falsos. 100 líneas de cableado para 5 líneas de prueba no son infrecuentes. Las pruebas de componentes alivian este problema.
No puedo hablar de ser una mejor práctica, pero esto es lo que hice en el pasado.
Pruebas unitarias:
- Cree pruebas unitarias para granos no triviales (es decir, la mayoría de sus granos relacionados con Spring)
- Use Mocks para servicios inyectados cuando sea práctico (es decir, la mayoría si no todo el tiempo).
- Use una convención de nomenclatura estándar para estas pruebas en el directorio de
test
del proyecto. UsarTest
oTestCase
como un prefijo o sufijo para el nombre de clase parece ser ampliamente practicado.
Pruebas de integración:
- Cree una
AbstractIntegrationTestCase
que configuraSpring
WebApplicationContext
para su uso en clases de prueba de integración. - Use una convención de nomenclatura para las pruebas de integración en el directorio de
test
. He utilizadoIntTest
oIntegrationTest
como prefijo o sufijo para estas pruebas.
Configure tres objetivos de test
Ant:
- test-all (o lo que sea que quieras nombrar): Ejecutar pruebas de unidad y de integración
- prueba: pruebas de unidad de ejecución (solo porque la
test
parece ser el uso más común para las pruebas unitarias) - prueba-integración: ejecutar las pruebas de integración.
Como se señaló, puede usar las convenciones de nomenclatura que tengan sentido para su proyecto.
En cuanto a separar la unidad de las pruebas de integración en un directorio separado, no creo que importe, siempre y cuando los desarrolladores y sus herramientas puedan encontrarlas y ejecutarlas fácilmente.
Como ejemplo, el último proyecto de Java en el que trabajé con Spring utilizó exactamente lo que se describió anteriormente, con pruebas de integración y pruebas de unidad que viven en el mismo directorio de test
. Los proyectos de Grails, por otro lado, separan explícitamente los directorios de pruebas de integración y unidad bajo un directorio general de pruebas.
Use la interfaz InitializingBean (implementa un método "afterPropertiesSet") o especifique un método init para sus beans. InitializingBean es generalmente más fácil porque no necesita recordar agregar el método init a sus beans.
Use afterPropertiesSet para asegurarse de que todo se inyecte como no nulo, si es nulo, genere una excepción.
la diferencia entre la prueba unitaria y la prueba de integración es que la prueba unitaria no carga necesariamente su contexto, usted se está enfocando en el código que ha escrito; funciona de manera rápida, es decir con y sin excepciones, burlándose de las llamadas dependientes en él. Pero en el caso de las pruebas de integración, cargas el contexto y realizas pruebas de extremo a extremo como escenarios reales.