Archive for : marzo, 2018

post image

Primer vistazo al desarrollo de pruebas unitarias con Mockito

El desarrollo de pruebas unitarias es un tema sencillo y fácil de comprender, pero este se complica cuando el sistema al que se le deben desarrollar pruebas, debe interactuar o se integra con sistemas externo.  Entiéndase como sistemas externos la base de datos, un servicio web, etc.

Cuando desarrollamos una prueba unitaria el objetivo es probar una funcionalidad de forma aislada o como su nombre lo indica de forma unitaria, por lo general sera un procesamiento antes o después de tener una interacción con un sistema externo, por ejemplo antes de guardar datos o después de obtener información desde la base de datos.

Dicho esto no nos interesa comprobar que la base de datos guarda la informacion o si recupera dicha informacion ya que no estamos probando la interaccion entre los diferentes componentes de nuestro sistema, con este punto de partida exponemos el siguiente tema al cual le deberemos aplicar prueba unitarias.

Descripcion de la funcionalidad

Se necesita un servicio que exponga mediante un método el calculo de interés aplicado a un monto determinado, dicho método recibida un identificador(dpi) con el cual se podrá recuperar la información de este identificador y así obtener su monto y aplicar el interés que corresponda.

Para mantener la sencillez solamente tendremos las siguientes reglas:

  • Si el monto de la deuda es menor a 1,500 el interes a aplicar es 5%
  • En caso contrario el interés a aplicar es de 9%
  • Si el dpi no existe se lanza un excepción personalizada

Test

Las pruebas unitarias se realizar con JUnit y Mockito todas bajo un proyecto java con Gradle.  Este proyecto puede ser clonado desde el siguiente repositorio:

git clone https://gitlab.com/zacapalug/gradle-mockito.git

El proyecto consta de las siguientes clases:

Con la clase FakeDTO se recrea una clase entity, la cual contiene las propiedades de un objeto que debería guardarse o recuperarse desde una base de datos.  La clase FakeBean simula el comportamiento que tendría un Bean con acceso a la base de datos, en el cual tiene métodos para recuperar información de dicha base de datos, dicha clase también se simula su inyección dentro de la clase FakeService.  En FakeService tenemos la lógica requerida en la Descripcion de la funcionalidad y la inyección del Bean con acceso a la base de datos.

El metodo calcularImpuesto de la calse FakeService, cumple con la funcionalidad requerida:

public double calcularImpuesto(long dpi) {
    final FakeDTO person = fakeBean.findByDpi(dpi);

    double interesAplicar = INTERES_A;

    if (person.getDeuda() > DEUDA_MINIMA) {
        interesAplicar = INTERES_B;
    }

    return person.getDeuda() * interesAplicar;
}

Analizando vemos que podemos realizar las siguientes pruebas:

  • Una prueba cuando el monto es mayor a 1500
  • Una prueba cuando el monto es menor a 1500
  • Una prueba donde no se encuentra el ID enviado

Las cuales hemos desarrollado en la clase FakeServiceTest.java.  La cual iniciaremos a detallar a continuación.

package com.tio_gt;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;

import com.tio_gt.excepciones.IdNoEncontradoException;

import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

public class FakeServiceTest {

    @Mock
    private FakeBean fakeBean;

    @InjectMocks
    private FakeService fakeService;

    @Before
    public void init() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void calcularImpuestoA() throws Exception {
        when(fakeBean.findByDpi(dpiPersonaA)).thenReturn(personaA);

        final Double calculo = fakeService.calcularImpuesto(dpiPersonaA);

        assertEquals(resultadoA, calculo);
    }

    @Test
    public void calcularImpuestoB() throws Exception {
        when(fakeBean.findByDpi(dpiPersonaB)).thenReturn(personaB);

        final Double calculo = fakeService.calcularImpuesto(dpiPersonaB);

        assertEquals(resultadoB, calculo);
    }

    @Test(expected = IdNoEncontradoException.class)
    public void calcularImpuestoPersonaInexistente() throws Exception {
        when(fakeBean.findByDpi(dpiPersonaC)).thenThrow(new IdNoEncontradoException());

        fakeService.calcularImpuesto(dpiPersonaC);
    }

    //<editor-fold defaultstate="collapsed" desc="Datos estaticos">
    private final long dpiPersonaA = 11223344L;
    private final long dpiPersonaB = 11223346L;
    private final long dpiPersonaC = 11223348L;

    private final FakeDTO personaA = new FakeDTO(dpiPersonaA, "Luis", "Morales", "Zacapa", 10000.00);
    private final FakeDTO personaB = new FakeDTO(dpiPersonaB, "Luis", "Morales", "Zacapa", 18000.00);

    private final Double resultadoA = 500D;
    private final Double resultadoB = 1620D;
    //</editor-fold>

}

En esta clase podemos encontrar 4 secciones importantes.De la linea 14 a la linea 18 podemos encontrar la primera sección, en la cual definimos nuestros Mocks, en este caso puntual creamos Mocks(@Mock) para fakeBean y para fakeService, ademas le indicamos a mockito que inyecte los mocks que cumplan con las dependencias dentro de el(@InjectMocks).

La segunda sección la podemos identificar de la linea de la linea 20 a la linea 23, en este bloque le indicamos a Mockito que inicie, inyecte y ejecute las operaciones necesarias para ejecutar nuestros tests, esto puede hacerse de varias formas, hemos utilizado esta ya que es una de las formas mas comunes y es compatible con la ejecución de tests en paralelo.

La tercera sección la corresponden los Tests como tal, teniendo de la linea 25 a la linea 48, la definición de los métodos que contienen las comprobaciones a realizar. El primer y segundo método tiene gran similitud,  en la primera linea especificamos el resultado requerido para un método especifico con las condiciones especificas, en otras palabras se especifica que cuando se ejecute findByDpi con el parámetro dado por el valor de una variable X.  Si vemos ambas lineas(la primera del método calcularImpuestoA y calcularImpuestoB.

when(fakeBean.findByDpi(dpiPersonA)).thenReturn(personA);

when(fakeBean.findByDpi(dpiPersonB)).thenReturn(personB);

Ambas configuran para que hacer el llamado a la función findByDpi, ya sea enviando el valor de dpiPersonaA o dpiPersonaB se retorne personaA o personaB, según sea el caso, ya que dicha función se ejecuta dentro la función calcular impuesto.

Con esto ya hemos quito la necesidad de hacer una consulta a la base de datos o cualquier otro sistema, que debería ser el encargado de devolverme los datos de ese dpi.  Prácticamente podemos indicar que when y thenReturn funcionan literalmente.

Luego tenemos en ambas funciones la linea donde se ejecuta la función a testear, almacenamos el resultado de obtenido por dicha función y luego se ejecuta el assert especifico.

Luego tenemos el método calcularImpuestoPersonaInexistente, el cual varia en que, en lugar de esperar un resultado esperaremos una excepción personalizada.

when(fakeBean.findByDpi(dpiPersonaC)).thenThrow(new IdNoEncontradoException());

Como ultima sección tenemos el bloque encerrado en el folder Datos estaticos, el cual inicia en la linea 50 y finaliza en la linea 60, este bloque corresponde con la data estática que deseamos probar, esta data la cual definimos y por ende conocemos su estado, y el resultado de aplicar los proceso o funciones que deseamos comprobar.  En otras palabras, es la fuente de datos a la que se le aplicara el procesamiento y con la que se comprobara que los resultados obtenidos sean los esperados.

Dependencias Gradle

Antes de poder ejecutar nuestras pruebas, necesitamos agregar las dependencias correspondientes en el archivo build.gradle

dependencies {
    testCompile 'junit:junit:4.12'
    testCompile 'org.mockito:mockito-core:2.9.0'
}

Ejecutar pruebas

Podemos ejecutar las pruebas de dos formas, ya sea al realizar un build

gradle clean build

O ejecutándolas directamente con el comando

gradle test

Una vez terminada la ejecución de las pruebas se puede verificar el reportes, el cual es generado en build/reports/tests/test/, en ese directorio puedes abrir el fichero index.html y observar resultados como el siguiente

Ahora vamos a realizar un cambio en el sistema para simular un error un humano, vamos a simular que un desarrollador ha equivocado los valores de los impuestos, En la clase FakeService.java vamos a cambiar los valores de las lineas 22 y 27. Y volvemos a ejecutar los tests

gradle test

Y volvemos a ver el reporte y podemos comprobar los errores detectados en nuestra fase de pruebas unitarias.

Con esto tenemos un ejemplo básico en donde se implementa pruebas unitarias con JUnit y Mockito.  El proyecto aunque utiliza clases dummies simula un problema real.  Esperamos estar subiendo mas temas sobre testing, tanto Unit Testing como Integration Testing.

Enviar correo desde Laravel con SendGrid

Paso 1:  Registrar la cuenta de SendGrid

  • Vaya a https://sendgrid.com
  • Haga clic en el botón Probar gratis
  • Complete todos los detalles necesarios
  • Espere a que SendGrid le envíe un correo electrónico para confirmar que su cuenta está provista.

Paso 2:  Cambia las configuraciones de correo en ELarchivo .env

Abra .env ubicado en la raíz de la aplicación, edite el archivo como se muestra a continuación

MAIL_DRIVER=smtp
MAIL_HOST=smtp.sendgrid.net
MAIL_PORT=587
MAIL_USERNAME=sendgrid_username
MAIL_PASSWORD=sendgrid_password
MAIL_ENCRYPTION=tls
MAIL_FROM_NAME="John Smith"
MAIL_FROM_ADDRESS=from@example.com

(más…)

¿Cómo usar la conexión de SQL Server en Laravel?

Pasos para configurar e instalar el driver para poder utilizar la conexión de SQL Server con el Framework Laravel en sistemas Linux.

1. sudo apt-get update
2. sudo apt-get install php-sybase

esto hará que Laravel use el controlador dblib en lugar de sqlsrv.

consulte este archivo para referencia Illuminate \ Database \ Connectors \ SqlServerConnector.php.

  1. abra este archivo:  /etc/freetds/freetds.conf

(más…)

post image

Debugeando una aplicación Java API RESTful con Visual Code y Gradle

Visual Studio Code desde que salio se convirtió en uno de mis IDES favoritos y de apoco se ha convertir en mi IDE predilecto, realmente a sido una de las grandes sorpresas que ha dado Microsoft al lanzar este software bajo el modelo OpenSource.

Aunque hay mucha documentación, vídeos, etc, que muestra la funcionalidad y personalización de este IDE he encontrado poca información de como debugear una aplicación Web Utilizando Gradle y este editor.

Antes de iniciar de lleno en la explicación, comentare una funcionalidad que hace que este IDE se mantenga simple y robusto, y al mismo tiempo una de las características que mas me gustan, tu puedes configurar que plugins se activan en los workspaces que tu configures.  Esto es genial de tantas maneras pero lo simplificare diciendo lo siguiente: vamos a cargar los plugins java(por ende algunos de los que recomendare en esta entrada) en los proyectos donde lo requiera y con esto evitaremos que si un proyecto no requiere determinados plugins, nuestro IDE siga muy liviano y con buen rendimiento.

Proyecto a utilizar

Ya que el framework web a utilizar no es el tema principal, simplificaremos en que utilizamos java spark, el cual es un framework realmente minimalista.  El cual a demás hace uso del estándar java servlet 3.x, con el cual podemos definir aplicaciones web dentro de aplicaciones .jar.  Este framework embebe un servidor jetty.

Para hacerte con el proyecto de demo, debes clonar el siguiente repositorio git publico y acceder al directorio:

git clone https://gitlab.com/zacapalug/gradle-vscode-debug.git
cd gradle-vscode-debug/

Una vez dentro del proyecto demos un primer vistazo sin entrar en detalle, ya que la mayoría de funcionalidad que este proyecto tiene es funcionalidad dummy con el objetivos puramente de prueba.  Dada esta aclaración procedemos a compilar y ejecutar el proyecto.

gradle clean build
gradle run

Con esto tendremos corriendo nuestra aplicación web en el puerto 8182, si quieres cambiarlo puedes ir a la clase Main en la linea 7.  Esta aplicación tiene tres métodos para nuestra API RESTful dummy

  1. http://127.0.0.1:8182/demo
  2. http://127.0.0.1:8182/status
  3. http://127.0.0.1:8182/cualquier-url
  4. http://127.0.0.1:8182/stop

Donde la primera simula un procesamiento de información, en el cual podemos definir varios breakpoints.  El segundo muestra información del request, con lo cual también podemos definir breakpoints interesantes.  El tercero hay poco que debugear y el ultimo detiene el servidor y muestra el respectivo mensaje.  Puedes copiar estar URLs e ir una a una en cualquier navegador web.

Plugins necesarios

Antes de listar los plugins requeridos para poder ejecutar nuestra practica, debemos ejecutar VSCode y abrir nuestro proyecto.

Acá podemos observar que el proyecto tiene la típica estructura de un proyecto java/gradle, así que instalaremos los plugins necesarios para este tipo de proyecto, yo en lo persona utilizo los siguientes:

Ejecutar la aplicación en modo debug

Para ejecutar el modo debug nuestra aplicación hemos agregado el task debug a nuestro fichero build.gradle.

Como podemos ver es un task bastante simple, donde configuramos las opciones necesarias al parámetro jvm-args del task run, terminamos configurando que al finalizar el task debug debe ejecutarse el task run, y debido que este lo acabamos de configurar, este task sera iniciado en modo debug.

Analizando los parámetros que se pasan a jvm-args, observación la definición del puerto al que debemos conectarnos para poder debugear nuestra aplicación, en este caso usamos el puerto 5005.

Con esto ya podemos ejecutar el comando gradle debug, y confirmar(como en la siguiente imagen) que el puerto de debug ya sido abierto.

Aunque el task ha sido ejecuta nuestra aplicación no ha iniciado a ejecutarse, esto por que el procesa esta esperado que se attache un debugger.  Podemos ver la configuración básica del plugin que hemos instalado en el fichero .vcode/launch.json.

Acá lo que debemos confirmar es que nos vamos a conectar al mismos puerto en que se ejecuto nuestra aplicación.  Esto lo podemos hacer en el menú de debug en la barra de herramientas de nuestro idea y presionando el botón play, teniendo previamente seleccionado el nombre asignado a nuestro debugger, en caso de tener otros debugger.

Una vez hecho esto podemos ver en la consola integrada como nuestra aplicación arranca y podemos ver como los paneles de debug son activados.

Vamos aponer un punto de interrupción en el archivo Rutas.java en la linea 44.

Una vez realizado esto podemos ir a nuestro navegador e ir al url http://127.0.0.1:8182/demo, y analicemos que podemos verificar en nuestro IDE.

Como podemos ver en la imagen, prácticamente con colocar el cursor sobre una imagen basta poder obtener el valor de esta, asi como otra información relevante.  Prácticamente es como lo que podemos hacer con IDEs como NetBeans, Eclipse, Intellij Idea o cualquier otro.

Cabe destacar que estos plugins aun se encuentran en modo Preview, pero me permiten poder debugear, al menos básicamente mis aplicaciones en mi IDE favorito(a la fecha).  Ademas hay mas temas de configuración, o otra herramienta como la consola de debug, que considero valdrá la pena explicar al tener una versión estable de estas utilidades.

Diferentes versiones de Java, SDKMAN al rescate

En esta entrada vamos a hablar de una herramientas muy útil, que me ha simplificado la vida, cuando me veo en la necesidad de estar alternando entre diferentes versión de java.  Este es un escenario muy común para un desarrollador, en especial si se llevan diferentes proyectos los cuales a su a vez tienen diferentes versión de java, maven, gradle o cualquier derivado de java.

El sitio principal de sdk tiene una gran cantidad de información y ejemplos, pero esta guía vamos a tratar de resumir y condensar este proceso de instalación de sdk y el proceso de instalación de software  mediante sdk.

El siguiente proceso es compatible con cualquier sistema UNIX-like, esto incluye Mac OSX, Linux, Cygwin y aunque no lo he probado en Solaris and FreeBSD, también los incluye.

Todos los scripts los ejecutaremos dentro un contenedor docker limpio, por lo que sera como si nunca lo hubiéramos instalador antes, recomendamos que también sigas los ejemplos de la misma forma, podrás practicar sin comprometer tu sistema principales y ademas puede repetir varias veces el proceso y cada vez inicias en un sistema limpio, en otras palabras desde cero y cuando ya estés lo suficientemente listo puedes aplicar lo aprendido en tu sistema principal.  Si te decides por utilizar docker puedes iniciar tu contenedor de la siguiente forma:

administrador@TIO-gt-dev ~/Descargas $ docker run -it --rm --name sdkman debian

Si quieres una guía de docker, espérala, pronto estará en esta comunidad.

Instalación

Para instalar sdkman basta con ejecutar el siguiente comando:

root@d704f9296a9b:/# curl -s "https://get.sdkman.io" | bash

En el proceso de instalación se te podrá requerir que instales algún paquete en caso de no cumplir, en la mayoría de casos puede ser unzip o zip, lo que se requiera.

Luego instalar revisa tu fichero ~/.bashrc o según tu distribución puede ser ~/.bash_profile, en este fichero deberías encontrar algo como:

root@d704f9296a9b:/# cat ~/.bashrc 
#THIS MUST BE AT THE END OF THE FILE FOR SDKMAN TO WORK!!!
export SDKMAN_DIR="/root/.sdkman"
[[ -s "/root/.sdkman/bin/sdkman-init.sh" ]] && source "/root/.sdkman/bin/sdkman-init.sh"
root@d704f9296a9b:/#

Para seguir utilizando la misma consola en la que te encuentra basta con que compiles este fichero.

root@d704f9296a9b:/# source ~/.bashrc

Con esto ya podemos comprobar que todo anda bien y usar el comando sdk, por ejemplo podemos ver la versión instalada con el siguiente comando:

root@d704f9296a9b:/# sdk version

SDKMAN 5.6.1+290
root@d704f9296a9b:/#

Comandos mas recurrentes

Siempre puedes consultar la documentación en consola para revisar en detalle cada comando de sdk.

root@d704f9296a9b:/# sdk

Usage: sdk <command> [candidate] [version]
       sdk offline <enable|disable>

   commands:
       install   or i    <candidate> [version]
       uninstall or rm   <candidate> <version>
       list      or ls   [candidate]
       use       or u    <candidate> [version]
       default   or d    <candidate> [version]
       current   or c    [candidate]
       upgrade   or ug   [candidate]
       version   or v
       broadcast or b
       help      or h
       offline           [enable|disable]
       selfupdate        [force]
       update
       flush             <candidates|broadcast|archives|temp>

   candidate  :  the SDK to install: groovy, scala, grails, gradle, kotlin, etc.
                 use list command for comprehensive list of candidates
                 eg: $ sdk list

   version    :  where optional, defaults to latest stable if not provided
                 eg: $ sdk install groovy

root@d704f9296a9b:/#

A continuación vamos a describir los comandos mas recurrentes y su forma de uso:

  • list, muestra los programas disponibles para instalar mediante sdk
  • install, instala el programa especificado
  • unistall, elimina el programa especificado
  • use, especifica la versión del programa a utilizar en esa sesión de consola
  • default, especifica la versión del programa para utilizar por default
  • current, muestra la versión en uso del programa especificado

Ejemplos

Resta lo mas interesante el área practica, en la que veremos casos de uso reales tanto del jdk como dos de las herramientas de build mas importante dentro del mundo Java, las cuales son grade y maven.

Practicando con JAVA

Antes de instalar java vamos a verificar las versiones que están disponibles para su instalación:

root@a4e0700b13e7:/# sdk list java

================================================================================
Available Java Versions
================================================================================
     9.0.4-oracle                                                                  
     9.0.1-zulu                                                                    
     9.0.0-zulu                                                                    
     8u161-oracle                                                                  
     8u152-zulu                                                                    
     8u144-zulu                                                                    
     8u131-zulu                                                                    
     7u141-zulu                                                                    
     6u93-zulu                                                                                                                                
================================================================================
+ - local version
* - installed
> - currently in use
================================================================================
root@a4e0700b13e7:/#

Como todo buen amante de la tecnológica nos instalaremos la ultima versión de java:

root@a4e0700b13e7:/# sdk add java 9.0.4-oracle

Verificamos que tenemos la versión correcta:

root@a4e0700b13e7:/# java -version
java version "9.0.4"
Java(TM) SE Runtime Environment (build 9.0.4+11)
Java HotSpot(TM) 64-Bit Server VM (build 9.0.4+11, mixed mode)
root@a4e0700b13e7:/#

Con esto estamos listo para trabajar día a día con lo ultimo de nuestro buen amigo java.

Ahora supongamos que nos llega un proyecto en que debemos trabajar y este requiere una versión posterior de java, tradicionalmente es trabajo tedioso y si abonamos el mantener las diferentes versión de maven o gradle, esto es mas tedioso a un, pues veamos que podemos hacer con sdkman.

Primero supongamos que debemos trabajar con la versión 7 del jdk, si tienes la versión exacta en hora buena, si no selecciona la mas cercana, por lo general java mantiene una gran compatibilidad entre sus actualizaciones menores.

root@a4e0700b13e7:/# sdk ls java

================================================================================
Available Java Versions
================================================================================
 > * 9.0.4-oracle                                                                  
     9.0.1-zulu                                                                    
     9.0.0-zulu                                                                    
     8u161-oracle                                                                  
     8u152-zulu                                                                    
     8u144-zulu                                                                    
     8u131-zulu                                                                    
     7u141-zulu                                                                    
     6u93-zulu                                                                     
================================================================================
+ - local version
* - installed
> - currently in use
================================================================================
root@a4e0700b13e7:/#

Una vez identificada la versión, en este caso seleccionamos la versión 8u152-zulu, procedemos a instalarlo, pero como ya tenemos instalada una versión sdk nos preguntara si queremos que sea nuestra versión por defecto, en esta caso le diremos que no, ya que solo deseamos utilizarla cuando estemos trabajando en el proyecto especifico:

root@a4e0700b13e7:/# sdk install java 8u152-zulu

Downloading: java 8u152-zulu

In progress...

######################################################################## 100.0%

Repackaging Java 8u152-zulu...

Done repackaging...

Installing: java 8u152-zulu
Done installing!

Do you want java 8u152-zulu to be set as default? (Y/n): n
root@a4e0700b13e7:/#

Si ahora verificamos la versión de java veremos que seguimos manteniendo la anterior, esto debido a que sdk seguira manteniendo como versión default la primera instalación que realizamos, veamos:

root@a4e0700b13e7:/# java -version
java version "9.0.4"
Java(TM) SE Runtime Environment (build 9.0.4+11)
Java HotSpot(TM) 64-Bit Server VM (build 9.0.4+11, mixed mode)
root@a4e0700b13e7:/#
root@a4e0700b13e7:/# sdk list java

================================================================================
Available Java Versions
================================================================================
 > * 9.0.4-oracle                                                                  
     9.0.1-zulu                                                                    
     9.0.0-zulu                                                                    
     8u161-oracle                                                                  
   * 8u152-zulu                                                                    
     8u144-zulu                                                                    
     8u131-zulu                                                                    
     7u141-zulu                                                                    
     6u93-zulu                                                                     
================================================================================
+ - local version
* - installed
> - currently in use
================================================================================
root@a4e0700b13e7:/#

Con esto podemos seguir usando la versión mas actualizada en todas nuestras tareas propias y si cambiamos al proyecto de turno, podemos cambiar la versión de la siguiente forma:

root@a4e0700b13e7:/# sdk use java 8u152-zulu

Using java version 8u152-zulu in this shell.
root@a4e0700b13e7:/# java -version
openjdk version "1.8.0_152"
OpenJDK Runtime Environment (Zulu 8.25.0.1-linux64) (build 1.8.0_152-b16)
OpenJDK 64-Bit Server VM (Zulu 8.25.0.1-linux64) (build 25.152-b16, mixed mode)
root@a4e0700b13e7:/#

Con esto ya estamos listo para trabajar con la versión de java requerida, y lo mejor si cambias de consola o cierras la consola activa, la versión por default seguirá siendo la misma que la instalada al principio.  En cambio si lo que necesitas es cambiar la versión por default también puedes realizarlo de la siguiente forma:

root@a4e0700b13e7:/# sdk default java 8u152-zulu

Default java version set to 8u152-zulu
root@a4e0700b13e7:/#

Con esto cubrimos de manera muy descriptiva el proceso de instalación de diferentes versiones de jdk.  A continuación veremos dos ejemplos, de manera mas resumida.

Practicando con Maven

root@a4e0700b13e7:/# sdk list maven

================================================================================
Available Maven Versions
================================================================================
     3.5.2                                                                         
     3.5.0                                                                         
     3.3.9                                                                         
================================================================================
+ - local version
* - installed
> - currently in use
================================================================================
root@a4e0700b13e7:/# sdk install maven 3.5.2

Downloading: maven 3.5.2

In progress...

######################################################################## 100.0%

Installing: maven 3.5.2
Done installing!

root@a4e0700b13e7:/# sdk install maven 3.3.9

Downloading: maven 3.3.9

In progress...

######################################################################## 100.0%

Installing: maven 3.3.9
Done installing!

root@a4e0700b13e7:/# sdk use maven 3.5.2
Setting maven version 3.5.2 as default.

Using maven version 3.5.2 in this shell.
root@a4e0700b13e7:/# sdk use maven 3.3.9

Using maven version 3.3.9 in this shell.
root@a4e0700b13e7:/# mvn -v
Apache Maven 3.3.9 (bb52d8502b132ec0a5a3f4c09453c07478323dc5; 2015-11-10T16:41:47+00:00)
Maven home: /root/.sdkman/candidates/maven/3.3.9
Java version: 1.8.0_152, vendor: Azul Systems, Inc.
Java home: /root/.sdkman/candidates/java/8u152-zulu/jre
Default locale: en_US, platform encoding: ANSI_X3.4-1968
OS name: "linux", version: "4.13.0-32-generic", arch: "amd64", family: "unix"
root@a4e0700b13e7:/#

Practicando con Gradle

root@a4e0700b13e7:/# sdk list gradle 

================================================================================
Available Gradle Versions
================================================================================
     4.6-rc-2             4.3.1                3.5                  2.2.1          
     4.6-rc-1             4.3-rc-4             3.4.1                2.2            
     4.6                  4.3-rc-3             3.4                  2.14.1         
     4.5.1                4.3-rc-2             3.3                  2.14           
     4.5-rc-2             4.3-rc-1             3.2.1                2.13           
     4.5-rc-1             4.3                  3.2                  2.12           
     4.5                  4.2.1                3.1                  2.11           
     4.4.1                4.2-rc-2             3.0                  2.10           
     4.4-rc-6             4.2-rc-1             2.9                  2.1            
     4.4-rc-5             4.2                  2.8                  2.0            
     4.4-rc-4             4.1                  2.7                  1.9            
     4.4-rc-3             4.0.2                2.6                  1.8            
     4.4-rc-2             4.0.1                2.5                  1.7            
     4.4-rc-1             4.0                  2.4                  1.6            
     4.4                  3.5.1                2.3                  1.5            

================================================================================
+ - local version
* - installed
> - currently in use
================================================================================
root@a4e0700b13e7:/# sdk install gradle 4.6
root@a4e0700b13e7:/# sdk install gradle 4.5
root@a4e0700b13e7:/# sdk use gradle 4.6

Using gradle version 4.6 in this shell.
root@a4e0700b13e7:/# gradle -v

------------------------------------------------------------
Gradle 4.6
------------------------------------------------------------

Build time:   2018-02-28 13:36:36 UTC
Revision:     8fa6ce7945b640e6168488e4417f9bb96e4ab46c

Groovy:       2.4.12
Ant:          Apache Ant(TM) version 1.9.9 compiled on February 2 2017
JVM:          1.8.0_152 (Azul Systems, Inc. 25.152-b16)
OS:           Linux 4.13.0-32-generic amd64

root@a4e0700b13e7:/# sdk use gradle 4.5

Using gradle version 4.5 in this shell.
root@a4e0700b13e7:/# gradle -v

------------------------------------------------------------
Gradle 4.5
------------------------------------------------------------

Build time:   2018-01-24 17:04:52 UTC
Revision:     77d0ec90636f43669dc794ca17ef80dd65457bec

Groovy:       2.4.12
Ant:          Apache Ant(TM) version 1.9.9 compiled on February 2 2017
JVM:          1.8.0_152 (Azul Systems, Inc. 25.152-b16)
OS:           Linux 4.13.0-32-generic amd64

root@a4e0700b13e7:/#

Es posible que tanto gradle, maven o cualquier otra herramienta basada en java e instalada con sdk necesiten cerrar el terminal actual, abrir uno nuevo o recompilar el fichero .bashrc o .bash_profile:

root@a4e0700b13e7:/# source ~/.bashrc

Espero que este documento sea de ayuda y sobre todo recomiendo que NO se utilize sdkman como una alternativa para NO actualizar las dependencias de tu proyecto.