Pages

lundi 3 septembre 2012

Comment écrire des tests unitaires pour tester les appels à des webservices via Spring-ws ? (2/2)

Dans le premier article (http://javamind-fr.blogspot.fr/2012/09/comment-ecrire-des-tests-unitaires-pour.html) nous avons vu comment configurer spring-ws et spring-ws-test et comment exposer un webservice à d’autres applications. Cet article traite du cas inverse et nous allons voir comment écrire un client de webservice et le tester.

Configuration du client
Spring-ws fournit une API qui permet de gérer la connexion à un webservice distant et de gérer la transformation des objets Java en XML. La classe WebServiceTemplate est la classe de base qui est initiée en lui ajoutant
  • Une factory de message (la même que pour écrire le serveur) 
  • Le marshaller et le unmarshaller (on utilise également le même) 
  • L’URI pour accéder au webservice. 
    <bean id="webServiceTemplate" 
        class="org.springframework.ws.client.core.WebServiceTemplate">
        <constructor-arg ref="messageFactory" />
        <property name="defaultUri" value="http://com.meteo.fake/process/meteo"/>
        <property name="marshaller" ref="jaxb2Marshaller" />
        <property name="unmarshaller" ref="jaxb2Marshaller" />
    </bean>


Classe d’appel du webservice
Comme vous pouvez le constater sur l’exemple ci dessous, l’appel à un webservice distant est très simple et nécessite que très peu de ligne de code.

public class MeteoClientWs {
   @Autowired
   private WebServiceTemplate webServiceTemplate;

   public ReponseWsMeteo getMeteoVille(String ville, Date date) {
      Preconditions.checkArgument(StringUtils.isNotEmpty(ville),"Renseignez la ville!");
      Preconditions.checkNotNull(date, "Saisissez la date d'interrogation!");

      //Preparation de l'objet permettant d'appeler le WS
      AppelWsMeteo appel = new AppelWsMeteo(ville, date);

     return (ReponseWsMeteo) webServiceTemplate.marshalSendAndReceive(appel);
   }
}


Tester le client en simulant le travail du serveur
Pour tester l’appel du webservice nous devons définir le mock MockWebServiceServer en lui spécifiant le webServiceTemplate. Ensuite avant d’appeler notre classe à tester nous agissons sur le mock pour indiquer ce qu’il nous retourne en fonction du message que nous lui passons.

Dans l’exemple ci-dessous je fais deux appels, le premier renvoie un message et le second renvoie une SoapFaultExecption.

@ContextConfiguration(locations = { "/communContext.xml","/clientWsContext.xml" })
@RunWith(SpringJUnit4ClassRunner.class)
public class MeteoClientWsTest {
   private MeteoClientWs meteoClientWs;
   @Autowired
   private WebServiceTemplate webServiceTemplate;
   private MockWebServiceServer mockServerWs;

   @Before
   public void setUp(){
      meteoClientWs = new MeteoClientWs();
      meteoClientWs.setWebServiceTemplate(webServiceTemplate);
      mockServerWs = MockWebServiceServer.createServer(webServiceTemplate);
   }

   @Test
   public void testGetMeteoVilleOk(){
      // Retour attendu du webservice
      Source responseOk = new StringSource("<reponseWsMeteo indiceDeConfiance=\"80\" ville=\"LYON\" tempsAnnonce=\"BEAU\" date=\"2012-07-16T00:05:26.203\"/>");
      mockServerWs.expect(anything()).andRespond(withPayload(responseOk));
      
      // On appelle la classe à tester 
      ReponseWsMeteo retour = meteoClientWs.getMeteoVille("LYON", new Date()); 
mockServerWs.verify();

      Assert.assertEquals("LYON", retour.getVille());
      Assert.assertEquals("BEAU", retour.getTempsAnnonce());
      Assert.assertEquals(Integer.valueOf(80), retour.getIndiceDeConfiance());
      Assert.assertEquals("Sun, 15 Jul 2012 22:05:26 GMT", DateUtil.formatDate(retour.getDate()));
   }

   @Test
   public void testGetMeteoVilleSoapFaultErrorKo(){
      mockServerWs.expect(anything()).andRespond(withServerOrReceiverFault("Ville inconnue!", Locale.FRANCE));
      try{
         meteoClientWs.getMeteoVille("LYON", new Date());
         Assert.fail();
      }
      catch (SoapFaultClientException e) {
         //Attendu
      }
      mockServerWs.verify();
   }
}

La fonction verify() du mock permet de vérifier que le webservice a bien été appelé. Si jamais votre code métier fait plusieurs appels successifs au webservice vous devez spécifier ce qu'il renverra à chaque fois via le mock. Par exemple

mockServerWs.expect(anything()).andRespond(withPayload(responseOk)); 
mockServerWs.expect(anything()).andRespond(withServerOrReceiverFault("Ville inconnue!", Locale.FRANCE)); 
 

Aucun commentaire:

Enregistrer un commentaire

Remarque : Seul un membre de ce blog est autorisé à enregistrer un commentaire.