¿Cómo puedo hacer una prueba unitaria de mi servicio web REST?

16

Soy nuevo en las pruebas unitarias, tengo un método web REST que solo llama a DB y completa un DTO. El pseudo código es

public object GetCustomer(int id)
{
  CustomerDTO objCust = //get from DB
  return objCust;
}

Mi duda es cómo escribir pruebas para estos métodos y tipo de pruebas (Integración / Unidad) que se incluirán. Y para las pruebas unitarias, ¿necesita golpear el DB? Si lo fuera, y paso una identificación de cliente y hago pocas afirmaciones, los datos podrían cambiar eventualmente resultando en fallas.

Creo que me falta algo aquí para entender estos conceptos.

Soleado
fuente
55
En el código que publicó, las cosas para probar son: (1) ¿Puede llamar a GetCustomer con un int como parámetro? (2) ¿Devuelve un objeto CustomerDTO? (3) ¿Es ese objeto poblado de la base de datos como se esperaba? (4) ¿Se produce un comportamiento esperado si se llama con un int que no corresponde a un cliente válido? Nada de eso tiene que ver con REST todavía. Cuando esté listo para escribir el código que responde a las solicitudes RESTful, entonces escribirá pruebas para ello.
DavidO
@DavidO: "¿Está ese objeto poblado de la base de datos como se esperaba?" definitivamente no es una prueba unitaria (en lo que respecta al código de OP). Esa es una prueba de integración.
Flater
Sí, estás en lo correcto. Si pudiera regresar y cambiar el comentario para mencionar que en una prueba de integración verificaría el componente de base de datos y, de lo contrario, se burlaría de él, haría esa edición, pero la ventana de edición para comentarios si 5 minutos, y el comentario se hizo seis hace años que. :)
DavidO

Respuestas:

18

Durante las pruebas unitarias, no se espera que realice pruebas con una base de datos, o al menos, no con una base de datos que no haya preparado para las pruebas unitarias. Las pruebas con una base de datos y, como tal, probar diferentes capas de su aplicación al mismo tiempo generalmente se consideran pruebas de integración . Con las pruebas unitarias, se supone que debe probar solo lo que hace su método, lo que devuelve dependiendo de los diferentes parámetros y cuándo (o no) debería fallar.

Es muy esperado que en su método realice llamadas a métodos X desde otras clases. No estás probando estos métodos X , así que lo que tienes que hacer es burlarte de estos métodos.

Supongo que está escribiendo su código en Java, en ese caso tiene excelentes marcos de burla como Mockito que pueden serle útiles. Independientemente de si usa o no un marco de imitación es su elección, solo diré que le ahorrarán mucho tiempo y el que mencioné al menos no es realmente complicado.

Si solo quieres escribir tu propio simulacro para experimentar, entonces supongamos que tienes la siguiente CustomerRepositoryclase:

public class CustomerRepository {
 public CustomerDTO getCustomer(int id) {
   ...
 }
}

Puede escribir su propia CustomerRepositoryclase burlada y sucia de la siguiente manera:

public class MockedCustomerRepository extends CustomerRepository {
 public boolean bThrowDatabaseException;
 public boolean bReturnNull;
 public boolean bReturnCustomerWrongId;
 public boolean bReturnCustomerWithId;
 public CustomerDTO getCustomer(int id) {
  if(bThrowDatabaseException) { 
    throw new DatabaseException("xxx"); 
  } else if(bReturnNull) { 
    return null; 
  } else if(bReturnCustomerWrongId) { 
    throw new CustomerNotExistException(id);
  } else if(bReturnCustomerWithId) { 
    return new CustomerDTO(id); 
  }
 }
}

Luego, en su caso de prueba, básicamente reemplaza su instancia "estándar" CustomerRepositorycon una instancia simulada que le permitirá probar su método para varios resultados de getCustomer:

public class CustomerRestTest {
  public void testGetCustomer_databaseFailure() {
    MockedCustomerRepository dto = new MockedCustomerRepository();
    dto.bThrowDataBaseException = true;
    yRestClass rest = new MyRestClass();
    rest.dto = dto;
    rest.getCustomer(0);
    // depending on what you do in your getCustomer method, you should check if you catched the exception, or let it pass, etc.. Make your assertions here

  public void testGetCustomer_customerNotExist() {
    // etc.
  }
}

En general, cada método de prueba debe probar una sola cosa, esto ayuda a mantener sus pruebas pequeñas y enfocadas en una tarea.

Voy a repetirlo :-) Escribir una clase burlada completa lleva un tiempo como ves. Considere usar un marco burlón, cuanto menos se escriba código, menos errores se cometen , ¿verdad? Burlarse de un método que arroja una excepción o devuelve un valor dado para un parámetro dado es pan comido y toma 2 o 3 líneas (con mockito al menos)

Espero que ayude a probar su método REST.

Jalayn
fuente
44
Por lo general, no tiene lógica dentro de sus clases DTO, especialmente ninguna que interactúe con su almacenamiento de datos.
JustAnotherUserYouMayKnowOrNot
1
Fue solo un ejemplo, pero tienes toda la razón. Voy a cambiar los ejemplos para que se adapten mejor a la teoría.
Jalayn