Pour montrer les capacités de JsMock, rien de tel que des exemples de code. Nous allons donc reprendre le code du premier billet (vous pouvez télécharger les sources en annexe du premier billet)

Installation

La première chose à faire est de télécharger JsMock et de l'ajouter dans le répertoire JsUnit (ou ailleurs, mais le tout est d'être cohérent lors de la déclaration dans le fichier HTML) , puis de l'importer à partir de notre fichier de tests SimpleCodeTest :

<script language="JavaScript" type="text/javascript" src="../jsmock.js"></script>


Exemple de code à mocker

Pour comprendre les mocks il vaux mieux faire interagir deux objets entre eux : cela permet de tester un objet et d'en mocker un autre. Ajoutons donc un objet ConfigParameter et définissons en une instance dans MyObjectToTest :

function ConfigParameter() {
        this.getAlertMessage = function(){
                return "alertMessage";
        }

        this.setParam = function(Aname, Avalue) {
                //this[name]=value
        }
}

function MyObjectToTest(){
        this.configParameter = new ConfigParameter();

        var message = "Not defined yet!";
        
        this.setMessage = function(messageParam){
                message = messageParam
        }

        this.getMessage = function(){
                return message;
        }

        this.getAlertMessage = function(){
               return this.configParameter.getAlertMessage();
        }

        this.setConfigValue = function(){
                this.configParameter.setParam("MyName", "MyValue");
        }

}


Mocker des valeurs de retour

Voici un exemple où nous allons mocker le retour de getAlertMessage :

function testMockReturnedValue() {
        // Actor
        MyObj = new MyObjectToTest();
        
        // Mock
        mockControl = new MockControl();
        mockConfig = mockControl.createMock(ConfigParameter);
        mockConfig.expects().getAlertMessage().andReturn("mock Alert Message");

        MyObj.configParameter = mockConfig;

        // Assert
        assertEquals("mock Alert Message", MyObj.getAlertMessage());
        
        mockControl.verify();
}

Vous remarquerez qu'à la différence de EasyMock en Java, il n'est pas nécessaire d'appeler la méthode replay()

La méthode vérify permet de vérifier que les méthodes mockées sont bien appelées le bon nombre de fois : si une méthode non défini par votre mock est appelée le test ne passera pas, en revanche vous pourriez avoir défini le comportement d'une méthode mais que cette dernière ne soit jamais appelée, dans ce cas, si vous n'appelez pas la méthode verify, le test passera mais vous ne saurez pas que la méthode n'a pas été appelée).


mocker des fonctions

Il est possible de simuler les comportement (le corps de la méthode) d'une fonction grâce à la méthode andStub :

function testStubFunction() {
        // Actor
        MyObj = new MyObjectToTest();
        
        // Mock
        mockControl = new MockControl();
        mockConfig = mockControl.createMock(ConfigParameter);
        mockConfig.expects().getAlertMessage().andStub(
                 function() { 
                        return "test";
                 } 
        );

        MyObj.configParameter = mockConfig;

        // Assert
        assertEquals("test", MyObj.getAlertMessage());
}


Simuler des exceptions

Il est également possible de simuler des exceptions avec la méthode andThrow :

function testThrow() {
        exception = false ;
        // Actor
        MyObj = new MyObjectToTest();
        
        // Mock
        mockControl = new MockControl();
        mockConfig = mockControl.createMock(ConfigParameter);
        mockConfig.expects().getAlertMessage().andThrow("Error !");

        MyObj.configParameter = mockConfig;

        try {   
        MyObj.getAlertMessage();
        } catch (e){
          exception = true;
        }

        assertEquals(true, exception);
}


Mocker des fonctions avec paramètres

Pour mocker une fonction avec des paramètres, vous avez deux possibilités : soit vous spécifiez le type des paramètres lors de la définition du mock, dans le cas où seul le type des paramètres vous importe. Pour cela utiliser TypeOf.isA()

function testFunctionWithTypedParameters() {
        // Actor
        MyObj = new MyObjectToTest();
        
        // Mock
        mockControl = new MockControl();
        mockConfig = mockControl.createMock(ConfigParameter);
        mockConfig.expects().setParam(TypeOf.isA(String),TypeOf.isA(String));

        MyObj.configParameter = mockConfig;


        MyObj.setConfigValue();

        mockControl.verify();
}

soit vous spécifiez la valeur des paramètres, si vous voulez vérifier que la fonction est appelée avec les bonnes valeurs :

function testFunctionWithParameters() {
        // Actor
        MyObj = new MyObjectToTest();
        
        // Mock
        mockControl = new MockControl();
        
        mockConfig = mockControl.createMock(ConfigParameter);
        mockConfig.expects().setParam("MyName", "MyValue");

        MyObj.configParameter = mockConfig;
        MyObj.setConfigValue();

        mockControl.verify();
}

J'espère que cela vous à donner envie de l'utiliser, car le Javascript est de plus en plus présent dans les applications web et les tests permettent de mieux découpler votre code et de le rendre plus robuste.

La troisième et dernière partie traitera de JsTester qui permet de tester du javascript coté serveur (JsUnit dispose d'une partie serveur mais elle n'est là que pour piloter les tests, il faut toujours avoir un navigateur). nous verrons ses avantages et ses inconvénients et comment l'intégrer avec Maven et JUnit.