Tengo un archivo de recursos que tiene algunas configuraciones. Tengo una clase ResourceLoader que carga la configuración de este archivo. Esta clase es actualmente una clase singleton instanciada con entusiasmo. Tan pronto como se carga esta clase, lee la configuración del archivo (la ruta del archivo se almacena como un campo constante en otra clase). Algunos de estos ajustes no son adecuados para pruebas unitarias. Por ejemplo, tengo tiempo de suspensión de hebras en este archivo, que puede ser horas para el código de producción, pero me gustaría que sea un par de milisegundos para las pruebas unitarias. Entonces tengo otro archivo de recursos de prueba que tiene un conjunto diferente de valores. Mi pregunta es ¿cómo hago para intercambiar el archivo de recursos principal con este archivo de prueba durante las pruebas unitarias? El proyecto es un proyecto maven y estoy usando testng como marco de prueba. Estos son algunos de los enfoques que yo '
Use @BeforeSuite y modifique la variable constante FilePath para apuntar al archivo de prueba y use @AfterSuite para apuntarlo nuevamente al archivo original. Esto parece estar funcionando, pero creo que debido a que la clase ResourceLoader se instancia con entusiasmo, no hay garantía de que el método @BeforeSuite siempre se ejecute antes de que se cargue la clase ResourceLoader y, por lo tanto, las propiedades antiguas se pueden cargar antes de cambiar la ruta del archivo. Aunque la mayoría de los compiladores cargan una clase solo cuando se requiere, no estoy seguro de si este es un requisito de especificación de Java. Entonces, en teoría, esto puede no funcionar para todos los compiladores de Java.
Pase la ruta del archivo de recursos como un argumento de línea de comando. Puedo agregar la ruta del archivo de recursos de prueba como argumento de línea de comando en la configuración segura en el pom. Esto parece un poco excesivo.
Use el enfoque en 1. y haga que ResourceLoader sea perezoso instanciado. Esto garantiza que si se llama a @BeforeMethod antes de la primera llamada a ResourceLoader.getInstance (). GetProperty (..), ResourceLoader cargará el archivo correcto. Esto parece ser mejor que los primeros 2 enfoques, pero creo que crear una instancia de clase única de perezoso hace que sea feo, ya que no puedo usar un patrón simple como convertirlo en una enumeración y tal (como es el caso de la instanciación ansiosa).
Esto parece un escenario común, ¿cuál es la forma más común de hacerlo?
fuente
Respuestas:
Todos los singletons instanciados ansiosamente o perezosamente son antipatrones . El uso de singletons hace que las pruebas unitarias sean más difíciles porque no hay una manera fácil de burlarse de singletons.
Método estático simulado
Una solución alternativa es usar PowerMock para burlarse del método estático que devuelve una instancia única.
Usar inyección de dependencia
Una mejor solución es usar la inyección de dependencia. Si ya usa un marco de inyección de dependencias (por ejemplo, Spring, CDI), refactorice el código para hacer
ResourceLoader
un bean administrado con alcance singleton .Si no utiliza un marco de inyección de dependencias, una refactorización fácil será realizar cambios en todas las clases utilizando el singleton
ResourceLoader
:Y luego en pruebas unitarias simulacro
ResourceLoader
usando MockitoConfiguración de externalización
Otro enfoque es colocar un archivo con la configuración de prueba debajo
src/test/resources
. Si almacena la configuración ensrc/main/resources/application.properties
, un archivo lasrc/test/resources/application.properties
anulará.Además, es una buena idea externalizar la configuración a un archivo no empaquetado en un JAR. De esta manera, el archivo
src/main/resources/application.properties
contendrá las propiedades predeterminadas y un archivo pasado usando el parámetro de línea de comandos anulará estas propiedades. Por lo tanto, un archivo con propiedades de prueba también se pasará como un parámetro de línea de comando. Vea cómo Spring maneja la configuración externalizada .Usar las propiedades del sistema Java
Un enfoque aún más sencillo es permitir la anulación de las propiedades predeterminadas con las Propiedades del sistema en el método
ResourceLoader.getInstance().getProperty()
y pasar las propiedades de prueba de esta manerafuente
Comprueba si estás en jUnit
También puede verificar en tiempo de ejecución si jUnit se está ejecutando y luego intercambiar la ruta. Eso funcionaría así ( no probado ):
fuente