Wanted : syntaxe pour remplacer une méthode d’un objet dans un test unitaire

December 17th, 2008

J’utilise le framework Mockito depuis quelques mois pour simplifier l’écriture de mocks dans mes tests unitaires.
Là où EasyMock ne m’a jamais convaincu, Mockito présente une syntaxe à la fois simple et puissante. Par contre, il m’arrive de vouloir remplacer une méthode bien précise d’un objet soumis au test et là, Mockito ne m’aide pas.

Voilà ce que je suis obligé d’écrire :

final FileTemplate mockFileTemplate = new FileTemplate();

CopyFileRule rule = new CopyFileRule("src.txt", "dest.txt") {
	@Override
	protected FileTemplate createFileTemplate() {
		return mockFileTemplate;
	}
};

Voilà la syntaxe que j’aimerais avoir :

CopyFileRule rule = intercept(new CopyFileRule("src.txt", "dest.txt"));

when(rule.createFileTemplate()).thenReturn(new FileTemplate());

Connaissez-vous un outil qui permettrait de faire ça ?

Blog ,

Améliorer la génération WSDL vers Java

November 28th, 2008

Chaque stack SOAP Java a ses propres outils pour générer des Stubs Java à partir d’un fichier de description WSDL. A une époque, les outils Axis ou XFire généraient des Stubs franchement différents pour le même WSDL. Maintenant, les outils sont à peu près d’accord sur le format.

La description suivante :

<complextype name="CredentialsHeader">
    <sequence>
        <element name="username" type="xsd:string"/>
        <element name="password" type="xsd:string"/>
    </sequence>
</complextype>

Va générer la classe Java suivante :

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "CredentialsHeader", propOrder = {"username", "password"})
public class CredentialsHeader {
    @XmlElement(required = true)
    protected String username;
    @XmlElement(required = true)
    protected String password;

    public String getUsername() {
        return username;
    }
    public void setUsername(String value) {
        this.username = value;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String value) {
        this.password = value;
    }
}

Ce POJO est minimaliste : pas de constructeur avec paramètres, pas de toString()

Résultat, le code client d’appel des WebServices est fastideux avec beaucoup d’appels de setters et les résultats renvoyés ne peuvent pas être simplement dumpés dans la console.

Bien sûr, il est possible d’ajouter tout cela à la main post-génération, ça n’a pas d’impact sur les appels de WebServices, mais c’est fastidieux.

La solution repose sur jaxb2-commons. Un ensemble de plugins qui vont enrichir la génération des Stubs.

Prenons un exemple avec Metro, la stack SOAP de Sun et un bon vieux script Ant :

< ?xml version="1.0" ?>
<project default="all" basedir=".">
    <taskdef name="wsimport" classname="com.sun.tools.ws.ant.WsImport">
        <classpath>
            <fileset dir="metro/lib">
                    <include name="**/*.jar"/>
             </fileset>
            <fileset dir="plugins">
                    <include name="**/*.jar"/>
             </fileset>
        </classpath>
    </taskdef>

    <target name="all">
        <wsimport xnocompile="true" wsdl="test.wsdl">
            <xjcarg value="-Xvalue-constructor"/>
            <xjcarg value="-Xcommons-lang"/>
        </wsimport>
    </target>
</project>
  • Le paramètre -Xvalue-constructor permet de générer des constructeurs avec paramètres en plus du constructeur par défaut.
  • Le paramètre -Xcommons-lang permet de générer les méthodes equals(), toString() et hashCode() en utilisant apache-commons-lang.

Blog , ,

Utiliser plusieurs langages. Oui, mais…

November 13th, 2008

S’il est de plus en plus admis que l’utilisation de plusieurs langages est un réflexe de bon développpeur, j’ai l’impression qu’il n’existe pas beaucoup d’outillage pour faire ça sérieusement. Par sérieusement, j’entends : gestion de configuration unifiée, environnement de développement unifié, intégration continue commune, gestion des dépendances, tests fit, …

Certains points sont plus faciles à résoudre que d’autres. Ainsi, pour la gestion de configuration, s’il est quasi impossible de trouver un outil intégré à tous les IDE de référence de chaque langage, il est par contre trivial d’utiliser un outil externe.

D’autres points sont plus complexes. Chaque langage a son propre système de makefile, que ce soit Ant, Maven, Nant, Rake… Il est possible de tout faire avec un bon vieux Ant ou make mais l’on voit bien que l’introduction d’un nouveau langage a des impacts non négligeables sur toute la chaîne et qu’il faudra mettre de coté certains outils spécialisés au profit d’autres outils plus généralistes donc à priori plus lourds à mettre en oeuvre.

Tout est une question d’équilibre et de temps disponible pour trouver cet équilibre. Pas étonnant que beaucoup d’équipes préfèrent s’en tenir à un seul langage par projet.

De mon coté, je suis en train de mélanger du C#, du Java, du RoR et des langages de scirpts (Groovy ou JRuby). Je cherche encore la bonne façon de le faire…

Blog , ,