lunes, 26 de julio de 2021

12 factor, Webcompere y JUnit: Como testear con variables de entorno/sistema

En un mundo orientado al despliegue descentralizado de nuestras aplicaciones en distintos entornos, la metodología a seguir para realizar estos despliegues es cada vez más importante. 12 factor es un referente en cuanto a metodologías a seguir. En este manifiesto se indican 12 pasos a seguir para mejorar el despliegue de nuestras aplicaciones independientemente del lenguaje o la plataforma donde vayamos a desplegarlo. 

Ya hemos hablado sobre esta metodología varias veces en nuestros posts, sobre todo en cuanto a lo que se refiere el apartado de configuración. La idea se centra en que es importante que nuestras aplicaciones sean agnósticas en cuanto a la configuración del mismo. Ya no se encuentren configuradas en función del entorno en el que se desplieguen, como podíamos hacer con los profiles de Maven. Sino que el código sea siempre el mismo, y el paquete que generemos con dicho código sea independiente del entorno en el que vayamos a desplegarlo. Esto nos evita problemas como que podamos desplegar un proyecto con la configuración de producción en un entorno no productivo, con los perjuicios que esto puede acarrear. 

La forma de llevar a cabo esto, es a través de la configuración a través de variables del sistema o del entorno. Cuyos valores sean obtenidos por la aplicación en tiempos de ejecución. Esto nos puede llevar a un pequeño problema a la hora de realizar nuestras pruebas unitarias. Y es que no tengamos una forma sencilla de setear y obtener estas.

Si ejecutáramos las pruebas a través de Eclipse, podríamos setear estas variables a través de las opciones de ejecución que nos habilita el propio Eclipse: Run As > Run Configurations. 


Esta solución que nos puede servir si ejecutamos a través del Eclipse, no nos sirve si ejecutamos dichas pruebas a través de Maven manualmente o en un pipeline. Por tanto es necesario buscar una solución a este problema. 

Para ello vamos a utilizar la librería: system-stubs-core la cual nos permitirá emular estas variables del entorno. Y si lo que deseamos es utilizarlas en nuestras pruebas con JUnit 5, indicaremos la librería system-stubs-jupiter.

<dependency>
	<groupId>uk.org.webcompere</groupId>
	<artifactId>system-stubs-jupiter</artifactId>
	<version>1.2.0</version>
	<scope>test</scope>
</dependency>

Esta emulación la podemos realizar de dos formas diferentes. Pero siempre partiendo con la inclusión de la anotación ExtendWith y asociarla a la clase SystemStubsExtension.

Por un lado podremos crear un atributo de clase de tipo EnvironmentVariables asociada a la anotación SystemStub. Y posteriormente asociar las variables de entorno a la instancia de la clase asociada a la anotación. 

Un sencillo ejemplo:

@ExtendWith(SystemStubsExtension.class)
public class TwelveFactorEnvTest {
    private final static String DECRIPTED = "DEESBC";
    private final static String ENCRIPTED = "zaa7UFiP4kDBY3TXjUcjuw==";
    private final static String JASYPT_PWD = "JASYPT_PWD";

    @SystemStub
    private static EnvironmentVariables environmentVariables;

    @BeforeAll
    public static void before() {
	environmentVariables.set(JASYPT_PWD, "123456789");
    }

    @Test
    public void decode() {
	StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
	encryptor.setPassword(System.getenv(JASYPT_PWD));
	String decryptedPassword = encryptor.decrypt(ENCRIPTED);
	assertThat(decryptedPassword, equalTo(DECRIPTED));
    }
}

Pero también lo podemos hacer incluso más sencillo, si pasamos como parámetro del método la clase EnvironmentVariables

@ExtendWith(SystemStubsExtension.class)
public class TwelveFactorSystemTest {
    private final static String DECRIPTED = "DEESBC";
    private final static String ENCRIPTED = "zaa7UFiP4kDBY3TXjUcjuw==";
    private final static String JASYPT_PWD = "JASYPT_PWD";

    @Test
    public void decodeWithAttribute(final EnvironmentVariables environmentVariables) {
	environmentVariables.set(JASYPT_PWD, "123456789");

	StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
	encryptor.setPassword(System.getenv(JASYPT_PWD));
	String decryptedPassword = encryptor.decrypt(ENCRIPTED);
	assertThat(decryptedPassword, equalTo(DECRIPTED));
    }
}

A igual que con las variables del entorno, podemos hacer algo parecido con las propiedades del sistema. Las cuales también se pueden indicar en el Eclipse a través de variables de la JVM o con la librería de WebCompere y su clase SystemProperties.

@ExtendWith(SystemStubsExtension.class)
public class TwelveFactorEnvTest {
    private final static String DECRIPTED = "DEESBC";
    private final static String ENCRIPTED = "zaa7UFiP4kDBY3TXjUcjuw==";
    private final static String JASYPT_PWD = "JASYPT_PWD";

    @BeforeAll
    public static void before(final SystemProperties properties) {
	properties.set(JASYPT_PWD, "123456789");
    }

    @Test
    public void decode(final SystemProperties properties) {
	StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
	encryptor.setPassword(System.getProperty(JASYPT_PWD));
	String decryptedPassword = encryptor.decrypt(ENCRIPTED);
	assertThat(decryptedPassword, equalTo(DECRIPTED));
    }
}

Con esto hemos conocido otra fantástica librería que nos puede ayudar en la ejecución de nuestras pruebas unitarias. 


No hay comentarios:

Publicar un comentario