web-dev-qa-db-fra.com

Méthode privée de la classe sous test utilisant JMockit

Je veux me moquer de la méthode privée d'une classe en cours de test, mais la méthode renvoie false deux premières fois lorsque la méthode est appelée, elle doit ensuite renvoyer false. Voici le code que j'ai essayé. la classe qui est testée

public class ClassToTest 
{
    public void methodToTest()
    {
        Integer integerInstance = new Integer(0);
        boolean returnValue= methodToMock(integerInstance);
        if(returnValue)
        {
            System.out.println("methodToMock returned true");
        }
        else
        {
            System.out.println("methodToMock returned true");
        }
        System.out.println();
    }
    private boolean methodToMock(int value)
    {
        return true;
    }
}

Classe de test

import org.junit.Test;
import static mockit.Deencapsulation.*;

import mockit.*;
public class TestAClass 
{
    @Tested ClassToTest classToTestInstance;
    @Test
    public void test1()
    {

        new NonStrictExpectations(classToTestInstance)
        {
            {
                invoke(classToTestInstance, "methodToMock", anyInt);
                returns(false);
                times = 2;

                invoke(classToTestInstance, "methodToMock", anyInt);
                returns(true);
                times = 1;

            }
        };

        classToTestInstance.methodToTest();
        classToTestInstance.methodToTest();
        classToTestInstance.methodToTest();

    }
}

Je l'ai fait pour obtenir les résultats souhaités

    final StringBuffer count = new StringBuffer("0");
    new NonStrictExpectations(classToTestInstance)
    {

        {
            invoke(classToTestInstance, "methodToMock", anyInt);
            result= new Delegate() 
            {
                boolean methodToMock(int value)
                {                   
                    count.replace(0, count.length(), Integer.valueOf(Integer.valueOf(count.toString())+1).toString());
                    if(Integer.valueOf(count.toString())==3)
                    {
                        return true;
                    }
                    return false;
                }
            };

        }
    };
12
Varun

Utiliser les attentes (ou StrictExpectations)

En utilisant une combinaison d'Expectations et Deencapsulation.invoke (), vous pouvez partiellement vous moquer de l'objet testé:

import org.junit.Test;
import static mockit.Deencapsulation.*;
import mockit.*;

public class TestAClass
{
    public static class ClassToTest 
    {
        public void methodToTest()
        {
            boolean returnValue = methodToMock(0);
            System.out.println("methodToMock returned " + returnValue);
        }

        private boolean methodToMock(int value) { return true; }
    }

    @Tested ClassToTest classToTestInstance;

    @Test
    public void partiallyMockTestedClass() {
        new Expectations(classToTestInstance) {{
            invoke(classToTestInstance, "methodToMock", anyInt);
            result = false;
            times = 2;
        }};

        classToTestInstance.methodToTest();
        classToTestInstance.methodToTest();
        classToTestInstance.methodToTest();
    }
}

Le test ci-dessus imprime:

methodToMock returned false
methodToMock returned false
methodToMock returned true

En général, bien sûr, nous devrions éviter de vous moquer des méthodes private. Cela dit, j’ai trouvé dans la pratique que est parfois utile, généralement lorsque vous utilisez une méthode privée qui effectue quelque chose de non trivial et qui a déjà été testée par un autre test; Dans un tel cas, il peut être beaucoup plus facile de se moquer de cette méthode privée lors d'un second test (pour une méthode publique différente ou pour un chemin différent via la même méthode publique) que la configuration des entrées/conditions nécessaires.

Utilisation de NonStrictExpectations (obsolète dans JMockit 1.23)

Il est tout aussi facile d'écrire le test avec NonStrictExpectations (la tentative initiale du PO n'a pas fonctionné uniquement parce que la même attente non stricte a été enregistrée deux fois , le deuxième enregistrement remplaçant le premier):

@Test
public void partiallyMockTestedClass() {
    new NonStrictExpectations(classToTestInstance) {{
        invoke(classToTestInstance, "methodToMock", anyInt);
        returns(false, false, true);
    }};

    classToTestInstance.methodToTest();
    classToTestInstance.methodToTest();
    classToTestInstance.methodToTest();
}

Utiliser un délégué

Si plus de flexibilité est nécessaire, nous pouvons toujours enregistrer un résultat Delegate-:

@Test
public void partiallyMockTestedClass() {
    new NonStrictExpectations(classToTestInstance) {{
        invoke(classToTestInstance, "methodToMock", anyInt);

        result = new Delegate() {
           boolean delegate() {
               boolean nextValue = ...choose next return value somehow...
               return nextValue;
           }
        }
    }};

    classToTestInstance.methodToTest();
    classToTestInstance.methodToTest();
    classToTestInstance.methodToTest();
}
11
Rogério

Cela fonctionne pour moi: -

        new MockUp<ClassToTest>() {
            @Mock
            boolean methodToMock(int value) {
                return true;
            }
        };
9
Kaushik

Ici, vous pouvez remplacer une méthode particulière de la classe de test avec un comportement fictif.  

Pour le code ci-dessous:

public class ClassToTest 
{
    public void methodToTest()
    {
        Integer integerInstance = new Integer(0);
        boolean returnValue= methodToMock(integerInstance);
        if(returnValue)
        {
            System.out.println("methodToMock returned true");
        }
        else
        {
            System.out.println("methodToMock returned true");
        }
        System.out.println();
    }
    private boolean methodToMock(int value)
    {
        return true;
    }
}

La classe de test serait:

public class ClassToTestTest{

    @Test
    public void testMethodToTest(){

        new Mockup<ClassToTest>(){
            @Mock
            private boolean methodToMock(int value){
                return true;
            }
        };

        ....    

    }
}
1
Amit Kaneria