Come posso testare unitamente il mio servizio web REST?

13

Sono nuovo al test delle unità, ho un metodo web REST che chiama solo DB e popola un DTO. Lo pseudo codice è

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

Il mio dubbio è come scrivere test per questi metodi e tipo di test (Integrazione / Unità) da includere. E per i test unitari, ha bisogno di colpire il DB. Se lo fosse e io passassi un id cliente e facessi alcune asserzioni, i dati potrebbero cambiare alla fine con conseguenti fallimenti.

Penso che mi manchi qualcosa qui a comprendere questi concetti.

    
posta Sunny 26.03.2013 - 15:26
fonte

1 risposta

16

Durante i test unitari non ci si aspetta di testare con un database, o almeno, non con un database che non si è preparato per il test unitario. Testare con un database e, in quanto tale, testare contemporaneamente diversi livelli della tua applicazione è generalmente considerato come test di integrazione . Con i test unitari dovresti testare solo ciò che fa il tuo metodo, ciò che ritorna in base a diversi parametri e quando (o non) dovrebbe fallire.

È molto probabile che nel tuo metodo tu effettui chiamate ai metodi X di altre classi. Non stai testando questi metodi X quindi quello che devi fare è simulare questi metodi.

Suppongo che tu stia scrivendo il tuo codice in Java, in questo caso hai dei fantastici framework di derisione come Mockito che potrebbe esserti utile. Che tu scelga o meno una struttura di derisione è la tua scelta, ti dirò solo che ti faranno risparmiare molto tempo e quello di cui ho parlato non è davvero complicato.

Se vuoi solo scrivere la tua simulazione personale per sperimentare, supponi di avere la seguente classe CustomerRepository :

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

Puoi scrivere la tua classe CustomerRepository derisa e sporca nel seguente modo:

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); 
  }
 }
}

Quindi, nel tuo caso di test sostituisci sostanzialmente l'istanza "standard" di CustomerRepository con un'istanza fittizia che ti consentirà di testare il tuo metodo per vari risultati di 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.
  }
}

Generalmente, ogni metodo di test dovrebbe testare solo una cosa, questo aiuta a mantenere i tuoi test piccoli e concentrati su un compito.

Ho intenzione di ripeterlo :-) Scrivere una lezione completamente derisa richiede un po 'di tempo come vedi. Prendi in considerazione l'utilizzo di un framework di simulazione, meno uno scrive codice, meno errori vengono commessi , giusto? Prendere in giro un metodo che genera un'eccezione o restituisce un dato valore per un dato parametro è un pezzo di torta e prende 2 o 3 linee (con almeno un mockito)

Spero che questo aiuti a testare il tuo metodo REST.

    
risposta data 26.03.2013 - 16:08
fonte

Leggi altre domande sui tag