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;
}
};
}
};
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.
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();
}
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();
}
Cela fonctionne pour moi: -
new MockUp<ClassToTest>() {
@Mock
boolean methodToMock(int value) {
return true;
}
};
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;
}
};
....
}
}