Buscar..


Cómo probar una aplicación de arranque de primavera simple

Tenemos una aplicación de arranque Spring de muestra que almacena los datos del usuario en MongoDB y estamos usando los servicios Rest para recuperar datos.

Primero hay una clase de dominio, es decir, POJO

@Document
public class User{
    @Id
    private String id;

    private String name;

}

Un repositorio correspondiente basado en Spring Data MongoDB

public interface UserRepository extends MongoRepository<User, String> {
}

Entonces nuestro controlador de usuario

@RestController
class UserController {
 
    @Autowired
    private UserRepository repository;
 
    @RequestMapping("/users")
    List<User> users() {
        return repository.findAll();
    }
 
    @RequestMapping(value = "/Users/{id}", method = RequestMethod.DELETE)
    @ResponseStatus(HttpStatus.NO_CONTENT)
    void delete(@PathVariable("id") String id) {
        repository.delete(id);
    }
 
    // more controller methods
}

Y finalmente nuestra aplicación de arranque de primavera.

@SpringBootApplication
public class Application {
    public static void main(String args[]){
     SpringApplication.run(Application.class, args);
    }
}

Si, digamos que John Cena, The Rock y TripleHHH eran los únicos tres usuarios en la base de datos, una solicitud a / users daría la siguiente respuesta:

$ curl localhost:8080/users
[{"name":"John Cena","id":"1"},{"name":"The Rock","id":"2"},{"name":"TripleHHH","id":"3"}]

Ahora para probar el código verificaremos que la aplicación funcione.

@RunWith(SpringJUnit4ClassRunner.class)   // 1
@SpringApplicationConfiguration(classes = Application.class)   // 2
@WebAppConfiguration   // 3
@IntegrationTest("server.port:0")   // 4
public class UserControllerTest {

    @Autowired   // 5
    UserRepository repository;

    User cena;
    User rock;
    User tripleHHH;

    @Value("${local.server.port}")   // 6
    int port;

    @Before
    public void setUp() {
        // 7
        cena = new User("John Cena");
        rock = new User("The Rock");
        tripleHHH = new User("TripleHH");

        // 8
        repository.deleteAll();
        repository.save(Arrays.asList(cena, rock, tripleHHH));

        // 9
        RestAssured.port = port;
    }

    // 10
    @Test
    public void testFetchCena() {
        String cenaId = cena.getId();

        when().
                get("/Users/{id}", cenaId).
        then().
                statusCode(HttpStatus.SC_OK).
                body("name", Matchers.is("John Cena")).
                body("id", Matchers.is(cenaId));
    }

    @Test
    public void testFetchAll() {
        when().
                get("/users").
        then().
                statusCode(HttpStatus.SC_OK).
                body("name", Matchers.hasItems("John Cena", "The Rock", "TripleHHH"));
    }

    @Test
    public void testDeletetripleHHH() {
        String tripleHHHId = tripleHHH.getId();

        when()
                .delete("/Users/{id}", tripleHHHId).
        then().
                statusCode(HttpStatus.SC_NO_CONTENT);
    }
}

Explicación

  1. Como cualquier otra prueba basada en Spring, necesitamos el SpringJUnit4ClassRunner para que se SpringJUnit4ClassRunner un contexto de aplicación.
  2. La anotación @SpringApplicationConfiguration es similar a la anotación @ContextConfiguration en que se usa para especificar qué contexto (s) de aplicación deben usarse en la prueba. Además, activará la lógica para leer las configuraciones específicas de Spring Boot, las propiedades, etc.
  3. @WebAppConfiguration debe estar presente para indicar a Spring que se debe cargar un WebApplicationContext para la prueba. También proporciona un atributo para especificar la ruta a la raíz de la aplicación web.
  4. @IntegrationTest se utiliza para indicar a Spring Boot que se debe iniciar el servidor web incorporado. Al proporcionar pares de nombre-valor separados por dos puntos o iguales, cualquier variable de entorno puede ser anulada. En este ejemplo, "server.port:0" anulará la configuración de puerto predeterminada del servidor. Normalmente, el servidor comenzaría a usar el número de puerto especificado, pero el valor 0 tiene un significado especial. Cuando se especifica como 0, le dice a Spring Boot que escanee los puertos en el entorno host e inicie el servidor en un puerto disponible aleatorio. Esto es útil si tenemos diferentes servicios que ocupan diferentes puertos en las máquinas de desarrollo y el servidor de compilación que podría colisionar con el puerto de la aplicación, en cuyo caso la aplicación no se iniciará. En segundo lugar, si creamos múltiples pruebas de integración con diferentes contextos de aplicación, también pueden chocar si las pruebas se ejecutan simultáneamente.
  5. Tenemos acceso al contexto de la aplicación y podemos usar el cableado automático para inyectar cualquier Spring Bean.
  6. El valor de @Value("${local.server.port}”) se resolverá con el número de puerto real que se utiliza.
  7. Creamos algunas entidades que podemos utilizar para la validación.
  8. La base de datos MongoDB se borra y reinicializa para cada prueba, de modo que siempre se validen en un estado conocido. Dado que el orden de las pruebas no está definido, es probable que la prueba testFetchAll () falle si se ejecuta después de la prueba testDeletetripleHHH ().
  9. Le indicamos a Rest Assured que use el puerto correcto. Es un proyecto de código abierto que proporciona un DSL de Java para probar servicios de descanso.
  10. Las pruebas se implementan utilizando Rest Assured. podemos implementar las pruebas utilizando TestRestTemplate o cualquier otro cliente http, pero uso Rest Assured porque podemos escribir documentación concisa utilizando RestDocs

Cargando diferentes archivos yaml [o propiedades] o anular algunas propiedades

Cuando usamos @SpringApplicationConfiguration , usará la configuración de application.yml [propiedades] que en ciertas situaciones no es apropiada. Entonces, para anular las propiedades podemos usar la anotación @TestPropertySource .

@TestPropertySource(
        properties = {
                "spring.jpa.hibernate.ddl-auto=create-drop",
                "liquibase.enabled=false"
        }
)
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(Application.class)
public class ApplicationTest{

    // ...

}

Podemos usar el atributo de propiedades de @TestPropertySource para anular las propiedades específicas que deseamos. En el ejemplo anterior, estamos anulando la propiedad spring.jpa.hibernate.ddl-auto a create-drop . Y liquibase.enabled . liquibase.enabled a false .

Cargando diferentes archivos yml

Si desea cargar totalmente un archivo yml diferente para la prueba, puede usar el atributo de ubicaciones en @TestPropertySource .

@TestPropertySource(locations="classpath:test.yml")
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(Application.class)
public class ApplicationTest{

    // ...

}

Opciones alternativas

Opción 1:

También puede cargar un archivo yml diferente si coloca un archivo yml en la test > resource directorio de test > resource

Opcion 2:

Usando la anotación @ActiveProfiles

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@ActiveProfiles("somename")
public class MyIntTest{
}

Puede ver que estamos usando la anotación @ActiveProfiles y estamos pasando el nombre como el valor.

Cree un archivo llamado application-somename.yml y la prueba cargará este archivo.



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow