J'ai un cours comme ci-dessous:
public class A {
public A(String test) {
bla bla bla
}
public String check() {
bla bla bla
}
}
La logique dans le constructeur A(String test)
et check()
sont les choses que je cherche à railler. Je veux des appels tels que: new A($$$any string$$$).check()
renvoie une chaîne factice "test"
.
J'ai essayé:
A a = mock(A.class);
when(a.check()).thenReturn("test");
String test = a.check(); // to this point, everything works. test shows as "tests"
whenNew(A.class).withArguments(Matchers.anyString()).thenReturn(rk);
// also tried:
//whenNew(A.class).withParameterTypes(String.class).withArguments(Matchers.anyString()).thenReturn(rk);
new A("random string").check(); // this doesn't work
Mais cela ne semble pas fonctionner. new A($$$any string$$$).check()
continue de parcourir la logique du constructeur au lieu de rechercher l'objet simulé de A
.
Le code que vous avez posté fonctionne pour moi avec la dernière version de Mockito et Powermockito. Peut-être que vous n'avez pas préparé A? Essaye ça:
A.Java
public class A {
private final String test;
public A(String test) {
this.test = test;
}
public String check() {
return "checked " + this.test;
}
}
MockA.Java
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
@RunWith(PowerMockRunner.class)
@PrepareForTest(A.class)
public class MockA {
@Test
public void test_not_mocked() throws Throwable {
assertThat(new A("random string").check(), equalTo("checked random string"));
}
@Test
public void test_mocked() throws Throwable {
A a = mock(A.class);
when(a.check()).thenReturn("test");
PowerMockito.whenNew(A.class).withArguments(Mockito.anyString()).thenReturn(a);
assertThat(new A("random string").check(), equalTo("test"));
}
}
Les deux tests doivent réussir avec mockito 1.9.0, powermockito 1.4.12 et junit 4.8.2
À ma connaissance, vous ne pouvez pas vous moquer des constructeurs avec mockito, seulement des méthodes. Mais, selon le wiki de la page de code Google de Mockito, il existe un moyen de simuler le comportement du constructeur en créant une méthode dans votre classe qui renvoie une nouvelle instance de cette classe. alors vous pouvez vous moquer de cette méthode. Ci-dessous se trouve un extrait directement du wiki Mockito :
Modèle 1 - utilisation de méthodes sur une ligne pour la création d'objets
Pour utiliser le motif 1 (test d’une classe appelée MyClass), vous devez remplacer un appel tel que
Foo foo = new Foo( a, b, c );
avec
Foo foo = makeFoo( a, b, c );
et écrire une méthode d'une ligne
Foo makeFoo( A a, B b, C c ) { return new Foo( a, b, c ); }
Il est important de ne pas inclure de logique dans la méthode. juste la ligne qui crée l'objet. La raison en est que la méthode elle-même ne sera jamais testée à l'unité.
Lorsque vous venez tester la classe, l'objet que vous testez sera en fait un espion Mockito, avec cette méthode surchargée, pour renvoyer une maquette. Ce que vous testez n’est donc pas la classe elle-même, mais une version très légèrement modifiée de celle-ci.
Votre classe de test peut contenir des membres tels que
@Mock private Foo mockFoo; private MyClass toTest = spy(new MyClass());
Enfin, dans votre méthode de test, vous simulez l’appel de makeFoo avec une ligne comme
doReturn( mockFoo ) .when( toTest ) .makeFoo( any( A.class ), any( B.class ), any( C.class ));
Vous pouvez utiliser des corrélateurs plus spécifiques que any () si vous souhaitez vérifier les arguments transmis au constructeur.
Si vous souhaitez simplement renvoyer un objet fictif de votre classe, je pense que cela devrait fonctionner pour vous. Dans tous les cas, vous pouvez en savoir plus sur la création d'objets moqueurs ici:
Sans utiliser Powermock .... Voir l'exemple ci-dessous, basé sur la réponse de Ben Glasser, car il m'a fallu un certain temps pour le résoudre.
Classe d'origine:
public class AClazz {
public void updateObject(CClazz cClazzObj) {
log.debug("Bundler set.");
cClazzObj.setBundler(new BClazz(cClazzObj, 10));
}
}
Classe modifiée:
@Slf4j
public class AClazz {
public void updateObject(CClazz cClazzObj) {
log.debug("Bundler set.");
cClazzObj.setBundler(getBObject(cClazzObj, 10));
}
protected BClazz getBObject(CClazz cClazzObj, int i) {
return new BClazz(cClazzObj, 10);
}
}
Classe de test
public class AClazzTest {
@InjectMocks
@Spy
private AClazz aClazzObj;
@Mock
private CClazz cClazzObj;
@Mock
private BClazz bClassObj;
@Before
public void setUp() throws Exception {
Mockito.doReturn(bClassObj)
.when(aClazzObj)
.getBObject(Mockito.eq(cClazzObj), Mockito.anyInt());
}
@Test
public void testConfigStrategy() {
aClazzObj.updateObject(cClazzObj);
Mockito.verify(cClazzObj, Mockito.times(1)).setBundler(bClassObj);
}
}
Mockito a des limitations en testant les méthodes finales, statiques et privées.
avec la bibliothèque de tests jMockit, vous pouvez effectuer quelques tâches très facilement et simplement comme ci-dessous:
Constructeur simulé d'une classe Java.io.File:
new MockUp<File>(){
@Mock
public void $init(String pathname){
System.out.println(pathname);
// or do whatever you want
}
};
Mock une méthode statique: