tutorial - pruebas unitarias java netbeans
¿Cómo comenzar un contenedor de prueba Jersey(Grizzly) una vez para todas las pruebas en una clase de prueba? (2)
Puede usar @BeforeClass y @AfterClass para anular el @Before y el @After lifecycle de JerseyTest. Aquí está la plantilla de código:
public abstract class MyJerseyTest {
private JerseyTest jerseyTest;
public MyJerseyTest(){
}
@BeforeClass
public void setUp() throws Exception {
initJerseyTest()
jerseyTest.setUp();
}
@AfterClass
public void tearDown() throws Exception {
jerseyTest.tearDown();
}
private void initJerseyTest() {
jerseyTest = new JerseyTest() {
@Override
protected Application configure() {
// do somthing like
enable(...);
set(...);
// create ResourceConfig instance
ResourceConfig rc = new ResourceConfig();
// do somthing like
rc.property(...);
rc.register(...);
return rc;
}
};
}
}
Espero que esto sea útil.
Estoy trabajando en arreglar las pruebas de integración en uno de los proyectos. Actualmente, todas las clases de prueba de integración extienden la clase JerseyTest. Al pasar por la clase JerseyTest, me di cuenta de que inicia y detiene el contenedor para cada método de prueba utilizando las anotaciones Antes y Después de Junit.
¿Por qué es esto necesario? ¿No es suficiente si sacamos el contenedor una vez, ejecutamos las pruebas y lo apagamos al final?
También usamos Spring y toma tiempo para que el contexto se inicialice.
Antes de Junit4, solucionamos esta limitación manipulándola manualmente utilizando indicadores booleanos.
@Before
public void setup() {
if(!containerStarted) {
// start
containerStarted = true;
}
// else do nothing
}
Tuvimos una situación similar, usando jersey plus spring como marco de inyección de dependencia (jersey-spring-bridge). Escribir prueba de integración con el framework JerseyTest
es complicado porque inicia el contenedor antes de una prueba y detiene el contenedor después de la prueba. Este enfoque podría tener una ventaja, pero es muy lento y complicado teniendo en cuenta el hecho de que la primavera realiza el escaneo y el autoenvío de los frijoles en todo momento.
¿Cómo inicializar un contenedor grizzly una vez y usarlo para todas las pruebas en una clase de prueba?
Para lograr lo anterior, seguí los siguientes pasos:
En la clase de prueba como variable de instancia, declare una instancia de HttpServer
como sigue
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext.xml" })
public class OrderResourceTest {
...
public static final String BASE_URI = "http://localhost:8989/";
private static HttpServer server = null;
...
...
}
Tenga en cuenta que no uso JerseyTest
porque quiero manejar el inicio / detención del contenedor de prueba yo mismo. Ahora, necesita utilizar @Before
y @AfterClass
para configurar la instancia del servidor. En @Before
configuraremos la instancia del server
modo que cargue nuestras definiciones de filtro / oyente personalizadas en el web.xml
(como cargar programáticamente el web.xml en server
instancia del server
).
@Before
public void setUp() throws Exception {
if (server == null) {
System.out.println("Initializing an instance of Grizzly Container");
final ResourceConfig rc = new ResourceConfig(A.class, B.class);
WebappContext ctx = new WebappContext() {};
ctx.addContextInitParameter("contextConfigLocation", "classpath:applicationContext.xml");
ctx.addListener("com.package.something.AServletContextListener");
server = GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), rc);
ctx.deploy(server);
}
}
Si nota que estoy usando @Before pero, la condición if lo hará funcionar como @BeforeClass. No recuerdo exactamente por qué no @BeforeClass
y creo que probablemente se deba a algunas de esas configuraciones dentro del bloque if. De todos modos, pruébalo si tienes curiosidad.
- Cree ResourceConfig con los recursos que se van a probar, esto incluye su Resource / Controller, ExceptionMapper si lo hay, cualquier otra clase que deba cargarse.
- Cree una instancia de WebappContext y luego agregue programáticamente todos los parámetros de inicio de contexto
web.xml
comoapplicationContext
por ejemplo. DondeapplicationContext
contiene configuraciones basadas en resortes. - Si tienes un oyente en tu web.xml, entonces debes agregarlos programáticamente como se muestra arriba
- Si tiene filtros u otra cosa, entonces necesita agregarlos programáticamente a
ctx
. - Inicialice el
server
con la instancia Grizzly proporcionándole URI e instancia deResourceConfig
- Ya ha creado programáticamente un
WebappContext
que no es más que, web.xml y ahora usa su método de despliegue para pasarle la instancia del servidor. Esto ejecutará las configuraciones deWebappContext
y lo desplegará enserver
instancia delserver
.
Y ahora tiene una prueba ejecutando una instancia de Grizzly con su web.xml más las configuraciones específicas del resorte aplicadas a la instancia.
El @AfterClass
podría verse como sigue
@AfterClass
public static void tearDown() throws Exception {
System.out.println("tearDown called ...");
if (server != null && server.isStarted()) {
System.out.println("Shutting down the initialized Grizzly instance");
server.shutdownNow();
}
}
Y una prueba de muestra utilizando un marco REST-assured
@Test
public void testGetAllOrderrs() {
List<Orders> orders= (List<Orders>)
when().
get("/orders").
then().
statusCode(200).
extract().
response().body().as(List.class);
assertThat(orders.size()).isGreaterThan(0);
}
La razón anterior funciona sin especificar la ruta base porque establezco la ruta base REST-asegurada de la siguiente manera
RestAssured.baseURI = "http://localhost:8989/";
Si no desea utilizar REST-asegurado, entonces
@Test
public void testGetAllOrders() {
Client client = ClientBuilder.newBuilder().newClient();
WebTarget target = client.target(BASE_URI);
Response response = target
.path("/orders")
.request(MediaType.APPLICATION_JSON)
.get();
assertThat(response.getStatus()).isEqualTo(200);
JSONArray result = new JSONArray(response.readEntity(String.class));
assertThat(result.length()).isGreaterThan(0);
}
Importaciones basadas en Jersey
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.grizzly.servlet.WebappContext;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.server.ResourceConfig;