Je suis très nouveau dans le test unitaire Java et j'ai entendu dire que le framework Mockito est vraiment bon pour les tests.
J'ai développé un serveur REST (méthodes CRUD) et je souhaite maintenant le tester, mais je ne sais pas comment?
Encore plus, je ne sais pas comment cette procédure de test devrait commencer. Mon serveur doit fonctionner sur localhost puis faire des appels sur cette URL (par exemple, localhost: 8888)?
Voici ce que j'ai essayé jusqu'à présent, mais je suis à peu près sûr que ce n'est pas la bonne façon.
@Test
public void testInitialize() {
RESTfulGeneric rest = mock(RESTfulGeneric.class);
ResponseBuilder builder = Response.status(Response.Status.OK);
builder = Response.status(Response.Status.OK).entity(
"Your schema was succesfully created!");
when(rest.initialize(DatabaseSchema)).thenReturn(builder.build());
String result = rest.initialize(DatabaseSchema).getEntity().toString();
System.out.println("Here: " + result);
assertEquals("Your schema was succesfully created!", result);
}
Voici le code de la méthode initialize
.
@POST
@Produces(MediaType.APPLICATION_JSON)
@Path("/initialize")
public Response initialize(String DatabaseSchema) {
/** Set the LogLevel to Info, severe, warning and info will be written */
LOGGER.setLevel(Level.INFO);
ResponseBuilder builder = Response.status(Response.Status.OK);
LOGGER.info("POST/initialize - Initialize the " + user.getUserEmail()
+ " namespace with a database schema.");
/** Get a handle on the datastore itself */
DatastoreService datastore = DatastoreServiceFactory
.getDatastoreService();
datastore.put(dbSchema);
builder = Response.status(Response.Status.OK).entity(
"Your schema was succesfully created!");
/** Send response */
return builder.build();
}
Dans ce cas de test, je souhaite envoyer une chaîne Json au serveur (POST). Si tout se passe bien, le serveur doit répondre avec le message suivant: "Votre schéma a été créé avec succès!".
Quelqu'un peut-il m'aider s'il vous plaît?
D'ACCORD. Ainsi, le contrat de la méthode est le suivant: Analyser la chaîne d'entrée au format JSON et renvoyer BAD_REQUEST
si elle est invalide. S'il est valide, créez une entité dans la datastore
avec différentes propriétés (vous les connaissez) et renvoyez OK
.
Et vous devez vérifier que ce contrat est rempli par la méthode.
Où Mockito aide-t-il ici? Eh bien, si vous testez cette méthode sans Mockito, vous avez besoin d'une vraie DataStoreService
et vous devez vérifier que l'entité a été créée correctement dans cette vraie DataStoreService
. C’est là que votre test n’est plus un test unitaire, mais c’est aussi un endroit trop complexe à tester, trop long et trop difficile à exécuter car il nécessite un environnement complexe.
Mockito peut vous aider en vous moquant de la dépendance de DataStoreService
: vous pouvez créer une maquette de DataStoreService
et vérifier que cette maquette est bien appelée avec l'argument d'entité approprié lorsque vous appelez votre méthode initialize()
dans votre test.
Pour ce faire, vous devez être capable d'injecter la DataStoreService
dans votre objet testé. Cela peut être aussi simple que de refactoriser votre objet de la manière suivante:
public class MyRestService {
private DataStoreService dataStoreService;
// constructor used on the server
public MyRestService() {
this.dataStoreService = DatastoreServiceFactory.getDatastoreService();
}
// constructor used by the unit tests
public MyRestService(DataStoreService dataStoreService) {
this.dataStoreService = dataStoreService;
}
public Response initialize(String DatabaseSchema) {
...
// use this.dataStoreService instead of datastore
}
}
Et maintenant, dans votre méthode de test, vous pouvez faire:
@Test
public void testInitializeWithGoodInput() {
DataStoreService mockDataStoreService = mock(DataStoreService.class);
MyRestService service = new MyRestService(mockDataStoreService);
String goodInput = "...";
Response response = service.initialize(goodInput);
assertEquals(Response.Status.OK, response.getStatus());
ArgumentCaptor<Entity> argument = ArgumentCaptor.forClass(Entity.class);
verify(mock).put(argument.capture());
assertEquals("the correct kind", argument.getValue().getKind());
// ... other assertions
}
Ce dont vous parlez ressemble plus à aux tests d’intégration et Mockito (ou tout autre framework moqueur) ne vous sera pas très utile.
Si vous voulez écrire le code de test unitaire que vous avez écrit, Mockito est certainement un outil utile.
Je vous suggère de lire davantage sur le moquage/les tests unitaires et sur les circonstances dans lesquelles il devrait être utilisé.
Mockito est (généralement) pour tester des portions de code; Par exemple, si vous utilisiez votre service REST sans vouloir effectuer un test de pile complète, vous simuleriez le service connecté au service REST, ce qui vous permettait de le faire précisément. systématiquement, testez le comportement spécifique.
Pour tester des parties internes du service REST (par exemple, une méthode de service spécifique) sans toucher une base de données, vous devez simuler le sous-système de la base de données, permettant ainsi de tester uniquement les internes du service, sans impliquer la base de données. Ce test appartient au module de service REST, pas au côté client.
Pour tester le service REST lui-même, vous utiliseriez une bibliothèque client réelle, créant ainsi un test d'intégration full-stack. Mockito pourrait être utilisé ici pour simuler des parties du client non liées à la consommation de service REST.
La meilleure méthode consiste à utiliser wiremock Ajouter les dépendances suivantes: com.github.tomakehurst wiremock 2.4.1 org.igniterealtime.smack smack-core 4.0.6
Définissez et utilisez le câble comme indiqué ci-dessous
@Rule
public WireMockRule wireMockRule = new WireMockRule(8089);
String response ="Hello world";
StubMapping responseValid = stubFor(get(urlEqualTo(url)).withHeader("Content-Type", equalTo("application/json"))
.willReturn(aResponse().withStatus(200)
.withHeader("Content-Type", "application/json").withBody(response)));
Je conviens que ce n'est pas un test unitaire, mais un test d'intégration. Quoi qu'il en soit, vous préférez jeter un coup d'œil aux tests du serveur et du serveur grizzly intégré. Pour résumer, ce code démarre le serveur grizzly (qui pourrait également démarrer la base de données) sur localhost: 8888, puis configure le client du maillot du client et envoie une demande POST dont la réponse doit être testée. Ceci est une intégration puisque vous testez le serveur et la base de données, vous pouvez utiliser mockito pour émuler la base de données, mais cela dépend de la relation entre votre serveur et votre base de données.
(test avec le maillot 1.11 et le grizzly 2.2)
@BeforeClass
public static void setUpClass() throws Exception {
// starts grizzly
Starter.start_grizzly(true);
Thread.sleep(4000);
}
@Before
public void setUp() throws Exception {
client = new Client();
webResource = client.resource("http://localhost:8888");
}
@Test
public void testPostSchemaDatabase() throws Exception {
{
String DatabaseSchema = "{ database_schema : {...}}";
logger.info("REST client configured to send: " + DatabaseSchema);
ClientResponse response =
webResource
.path("/initialize")
.type("application/json")
.post(ClientResponse.class, DatabaseSchema);
//wait for the server to process
Thread.sleep(2000);
assertEquals(response.getStatus(), 204);
//test the response
}
}
@After
public void after() throws JSONException
{
//probably you want to delete the schema at database and stop the server
}