En un anterior serie de entradas de blog Expliqué cómo usar TestContainers para tus pruebas Junit de Java. Algunos de los temas que no abordamos fueron acerca de cómo probar N1QL, crear tus propios buckets, índice etc... Este post será sobre la construcción de... Spring Data Couchbase casos de prueba y cubrir esas cuestiones que dejamos fuera.
Puerto no configurable por cable
Una de las limitaciones que tenemos actualmente en Couchbase Server es que no se puede cambiar algunos de los puertos por defecto. Esto es un problema con Docker ya que es cambiar los puertos sólo se notifica lo contrario. Esto puede ser genial porque significa que puedes tener varias instancias de Couchbase corriendo en la misma máquina. Pero desafortunadamente no funcionará así que algunos puertos tendrán que ser arreglados. Esto puede ser declarado bastante fácilmente con TestContainers usando el método addFixedExposedPort.
|
1 2 3 4 5 6 7 8 9 10 |
@Override protected void configure() { addExposedPorts(8091, 11207, 11210, 11211, 18091, 18092, 18093); addFixedExposedPort(8092, 8092); addFixedExposedPort(8093, 8093); addFixedExposedPort(8094, 8094); addFixedExposedPort(8095, 8095); setWaitStrategy(new HttpWaitStrategy().forPath("/ui/index.html#/")); } |
Con eso fuera del camino, nuestro Java SDK será capaz de conectarse a N1QL.
Caso de prueba abstracto de Spring Data Couchbase Docker
El objetivo aquí es crear un caso de prueba abstracto que será utilizado por cualquier clase que necesite una instancia de Couchbase y Spring Data Couchbase configurado. Se empieza como en los posts anteriores instanciando un campo CouchbaseContainer. Como estamos probando Spring Data configuramos el soporte para Index, Query y añadimos FTS para más adelante.
Para asegurarse de que esta clase ejecutará las pruebas de su aplicación, añada el parámetro @RunWith(SpringRunner.class) anotación. Y para asegurarte de que la configuración de tu aplicación se prueba tan bien como nuestra configuración personalizada, añade @SpringBootTest(classes = {GittalentBackendApplication.class, AbstractSPDataTestConfig.CouchbaseTestConfig.class}).
Ahora hablando de configuración personalizada, ¿qué necesitamos? Queremos anular la configuración por defecto de Couchbase de la aplicación. Para ello necesitamos implementar un CouchbaseConfigurer. Esta interfaz define todos los bean necesarios para que Spring Data Couchbase funcione correctamente. Proporciona instancias para CouchbaseEnvironment, ClusterInfo, Cluster y Bucket.
Todos ellos provendrán de nuestra configuración de CouchbaseContainer antes de ejecutar las pruebas. Así que tenemos que asegurarnos de que el Contenedor está funcionando y listo antes de inicializar todos los beans. Esto se puede conseguir añadiendo un método init() anotado con @PostConstruct. Esto nos permitirá primero asegurarnos de que el contenedor se está ejecutando, y luego configurar cosas adicionales. En el siguiente ejemplo configuramos un cubo llamado default y configuramos el tipo de índice para que sea MOI.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
@RunWith(SpringRunner.class) @SpringBootTest(classes = {GittalentBackendApplication.class, AbstractSPDataTestConfig.CouchbaseTestConfig.class}) public abstract class AbstractSPDataTestConfig { public static final String clusterUser = "Administrator"; public static final String clusterPassword = "password"; @ClassRule public static CouchbaseContainer couchbaseContainer = new CouchbaseContainer() .withFTS(true) .withIndex(true) .withQuery(true) .withClusterUsername(clusterUser) .withClusterPassword(clusterPassword); @Configuration static class CouchbaseTestConfig implements CouchbaseConfigurer { private CouchbaseContainer couchbaseContainer; @PostConstruct public void init() throws Exception { couchbaseContainer = AbstractSPDataTestConfig.couchbaseContainer; BucketSettings settings = DefaultBucketSettings.builder() .enableFlush(true).name("default").quota(100).replicas(0).type(BucketType.COUCHBASE).build(); settings = couchbaseCluster().clusterManager(clusterUser, clusterPassword).insertBucket(settings); couchbaseContainer.callCouchbaseRestAPI("/settings/indexes", "indexerThreads=0&logLevel=info&maxRollbackPoints=5&storageMode=memory_optimized", "Administrator", "password"); waitForContainer(); } public void waitForContainer(){ CouchbaseWaitStrategy s = new CouchbaseWaitStrategy(); s.withBasicCredentials(clusterUser, clusterPassword); s.waitUntilReady(couchbaseContainer); } @Override @Bean public CouchbaseEnvironment couchbaseEnvironment() { return couchbaseContainer.getCouchbaseEnvironnement(); } @Override @Bean public Cluster couchbaseCluster() throws Exception { return couchbaseContainer.geCouchbaseCluster(); } @Override @Bean public ClusterInfo couchbaseClusterInfo() throws Exception { Cluster cc = couchbaseCluster(); ClusterManager manager = cc.clusterManager(clusterUser, clusterPassword); return manager.info(); } @Override @Bean public Bucket couchbaseClient() throws Exception { return couchbaseContainer.geCouchbaseCluster().openBucket("default"); } } } |
Una vez que tenemos este caso de prueba abstracto, todo lo que tenemos que hacer es crear una clase que lo extienda y empezar a escribir pruebas. Aquí podemos inyectar Servicios de nuestra aplicación así como un Bucket de nivel inferior. Lo que ves en este test es primero una llamada a un servicio importador que crea documentos. Luego creamos un índice en el bucket por defecto y probamos una consulta en él.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public class GitTalentGHImportTests extends AbstractSPDataTestConfig { @Autowired private GithubImportService githubImportService; @Autowired private Bucket bucket; @Test public void importDevAdvocateTeam(){ githubImportService.importOneDeveloper("ldoguin"); N1qlQueryResult result = bucket.query(N1qlQuery.simple("CREATE PRIMARY INDEX ON default")); N1qlQuery query = N1qlQuery.simple("SELECT * FROM default WHERE developerInfo.username = 'ldoguin'"); result = bucket.query(query); N1qlQueryRow row = result.rows().next(); Assert.assertNotNull(row); } } |
Como se puede ver una vez creado el caso de prueba Abstracto, la cantidad de código es realmente mínima y corresponde exactamente a lo que se quiere probar.
[...] Laurent Doguin, defensor de los desarrolladores de Couchbase, ha elaborado un buen artículo sobre cómo probar aplicaciones Couchbase de Spring Data con contenedores de prueba y [...]
Hola,
Estoy teniendo problemas al hacer varios archivos que extienden la clase Abstract.
¿Puedes probar en tu lado? A ver si hay algo que estoy haciendo mal...
Gracias de antemano,
Saludos,