REST API
Le API REST o meglio RESTful, sono oggi molto utilizzate, presentano infatti molteplici vantaggi, in particolar modo la semplicità di utilizzo ed il fatto di utilizzare il protocollo HTTP, le rendono una standard de facto per il World Wide Web. Vengono utilizzate praticamente ovunque e da chiunque, basta colleagarsi ad un sito del genere per capire la vastità dell’universo REST.
Restfuse
Ma andiamo al sodo, per un progetto sul quale sto lavorando al momento, avevo la necessità, non solo di sviluppare un’API REST ma anche di eseguire dei test di integrazione per verificare che tutte le chiamate realizzate, funzionassero in modo corretto.
Questo post su CodingJam mi ha ispirato.
I possibili framework infatti per eseguire una serie di Test in ambiente REST non mancano, come potete verificare nell’ottimo post citato.
La mia scelta però è andata su Restfuse, per la presunta semplicità, e per il fatto che fosse un’estensione di JUnit, la più famosa libreria per i test automatici nel mondo Java.
Devo subito fare una premessa doverosa, al momento il progetto Restfuse sembra in stallo, si capisce subito dal fatto che l’homepage del progetto restituisce un’allarmante 404 Not Found.
Non mi sono comunque lasciato intimidire da questo funesto segnale ed ho iniziato a documentarmi sul repository Github del progetto.
La documentazione in rete su questo progetto non è molto ampia e tutto quello che c’è ruota intorno al repository Github.
Installazione della Libreria
Il modo migliore per gestire le dipendenze delle librerie in un progetto java è sicuramente tramite Maven, riporto quindi la dipendenza da aggiungere al proprio Maven POM.
La libreria è perfettamente presente su Maven Central, quindi non serve aggiungere altri repository al proprio POM.
<dependency>
<groupId>com.restfuse</groupId>
<artifactId>com.eclipsesource.restfuse</artifactId>
<version>1.2.0</version>
</dependency>
Se non fosse possibile utilizzare Maven, nella sezione download del sito ufficiale è possibile scaricare la libreria.
Esempio di test con Restfuse
Passiamo subito al codice di esempio presente nel repository del progetto.
Primo esempio
@RunWith( HttpJUnitRunner.class )
public class SimpleHttpTest {
@Rule
public Destination restfuse = new Destination( this, "http://restfuse.com" );
@Context
private Response response;
@HttpTest( method = Method.GET, path = "/" )
public void checkRestfuseOnlineStatus() {
assertOk( response );
}
}
Come si vede il tutto è perfettamente configurabile tramite Annotations, @RunWith
è la direttiva con la quale scegliamo la classe chi eseguirà i nostri test, come dicevo all’inizio del post, alla fine Restfuse è un’estensione di JUnit.
L’Annotation @HttpTest
contrassegna il test vero e proprio che vogliamo eseguire.
Come possiamo vedere l’Annotation è composta da diversi parametri ovviamente il method
che indica il verbo HTTP della nostra API ed il path
ovvero il percorso nel quale risponde la nostra API.
Secondo esempio
Quest’esempio è molto semplice, passiamo ad un’esempio leggermente più complesso in modo da conoscere meglio Restfuse. L’esempio è disponibile a questo indirizzo.
RunWith(HttpJUnitRunner.class)
public class DynamicPathTest {
@Rule
public Destination restfuse = getDestination();
@Context
private Response response;
@HttpTest(method = Method.GET, path = "/{file}.jar")
public void checkRestfuseDownloadJarStatus() {
assertOk( response );
}
@HttpTest(method = Method.GET, path = "/{file}-javadoc.jar")
public void checkRestfuseDownloadDocsStatus() {
assertOk( response );
}
private Destination getDestination() {
Destination destination = new Destination( this,
"http://search.maven.org/remotecontent?filepath="+"com/restfuse/com.eclipsesource.restfuse/{version}/" );
RequestContext context = destination.getRequestContext();
context.addPathSegment( "file", "com.eclipsesource.restfuse-1.1.1" ).addPathSegment( "version", "1.1.1" );
return destination;
}
}
In questo esempio la differenza principale con quello precedente sta nel metodo getDestination()
, attraverso questo metodo infatti possiamo settare i vari parametri nel path che andremo ad utilizzare nei nostri test, nel caso specifico il parametro {file}
. Una cosa molto importante da sapere è che il metodo getDestination()
dell’esempio viene eseguito per ciascun test.
Ultimo esempio
L’ultimo esempio che voglio mostrare è un’inserimento di dati tramite POST.
@RunWith(HttpJUnitRunner.class)
public class RestTestIT extends Assert {
@Rule
public Destination destination = getDestination();
@Context
private Response response;
private static ResourceBundle finder = ResourceBundle.getBundle("my-music-service");
private Destination getDestination() {
Destination destination = new Destination(this, finder.getString("destination.url.integration"));
RequestContext context = destination.getRequestContext();
context.addPathSegment("song", "Under Pressure")
.addPathSegment("artist", "David Bowie");
return destination;
}
@HttpTest(method = Method.POST, path = "/music/{song}/{artist}",
order = 1, content = "dummy")
public void testAddTrack() {
assertOk(response);
}
@HttpTest(method = Method.GET, path = "/music/{song}", order = 2)
public void testGetSong() {
assertOk(response);
}
In questo esempio viene eseguita un POST di alcuni dati.
Una cosa curiosa che mi ha fatto perdere del tempo è il parametro content
.
Nel caso infatti che si debbano inserire dei parametri semplicemente tramite il path
dell’API, senza quindi contenuto nel body, nella versione attuale della libreria non è permesso di non inserire o di lasciare vuoto il parametro in questione pena un NullPointerException, da qui il valore content="dummy"
utilizzato.
Maggiori informazioni su questo bug le potete trovare qui.
Un’altro parametro molto importante è order
che permette di definire un’ordine di esecuzione dei test.
Questo parametro farà storcere il naso ai puristi dell’idempotenza dei test, ma in taluni casi può essere molto utile.
Conclusioni
Restfuse è sicuramente una buona libreria per testare REST API, ma presenta diversi bug al momento ed un supporto a tratti latitante, speriamo davvero che il progetto riparta in qualche modo.
Aggiungo questo ulteriore repo Github di Andreas Mihm che aggiunge ulteriori esempi, rispetto a quello originale citato in precedenza.
Se qualcuno è interessato all’utilizzo di Maven con il plugin failsafe, consiglio l’ottimo post sempre su Coding Jam.
Per adesso è tutto.
Come sempre Stay Tuned!
Image Courtesy of http://developer.decarta.com
Source: antonioscatoloni.site