2013-05-16 3 views
2

J'ai la structure suivanteEst-ce que mockito change les objets?

public class A{...} 

public class B extends A{ 
    private C cObject; 
    private Object otherValue; 

    B(){ 
     cObject = new C(this); 
    } 
} 

public class C{ 
    private B bObject; 

    C(B bObject){ 
     this.bObject = bObject; 
    } 
} 

Je veux tester une méthode de la classe B. J'utilise Mockito parce que je dois railler une autre méthode de B afin de tester la méthode que je veux tester. Donc, dans mon test, je déclare l'objet B comme @Spy, j'appelle MockitoAnnotations.initMocks(this); et enfin je me moque de la méthode en utilisant doReturn().when().method();

Maintenant, je Refaites le test et il échoue. Ma surprise vient quand je le débogue et je me rends compte que quand je suis dans l'objet B, la valeur du champ otherValue est par exemple X mais quand je suis en C, la valeur de this.bObject.otherValue n'est pas X mais null.

Puisque j'ai créé l'objet C dans B avec new C(this);, B et C.bObject ne devraient-ils pas tous être le même objet et contenir donc les mêmes valeurs?

NOTE: Je l'ai aussi essayé sans espionnage au profit de l'objet et se moquant de la méthode et il fonctionne, donc la vraie question est:

Est-ce que Mockito remplacer mon objet avec un autre objet quand j'espionne il? Et dans ce cas, que puis-je faire pour le faire fonctionner? Une explication plus simple pourrait être: Je veux tester un objet B, cet objet B crée une instance d'un objet C qui se passe (ce) en paramètre. J'ai besoin de Spy l'objet B afin que je crée dans mon test une instance de B, puis appelez MockitoAnnotations.initMocks(this);. Les deux objets (celui du test et celui de l'instance de C) après cet appel sont-ils toujours le même objet ou mockito le remplace par un nouvel objet?

Répondre

2

L'exemple B seront construits avant d'être espionné, de sorte que la référence qui reçoit C est l'objet réel B et non pas l'instance espionné.

Vous ajoutez un comportement à l'instance espion qui est en effet un objet différent de celui que possède C.bObject, donc le comportement n'est pas appliqué. De même, le réglage b.otherValue n'aboutira pas à la définition de b.cObject.bObject.otherValue.

Vous pouvez voir que ce sont des objets différents - en supposant un défaut toString est présent:

final B b = Mockito.spy(new B()); 

System.out.println("spied: " + b); 
System.out.println("b.cObject.bObject: " + b.cObject.bObject); 

Il devrait produire quelque chose le long des lignes de:

spied: [email protected] 
b.cObject.bObject: [email protected] 

Peut-être que vous pourriez utiliser la réflexion pour définir b.cObject.bObject champ à l'instance espionnée? Par exemple:

final Field f = C.class.getDeclaredField("bObject"); 
f.setAccessible(true); 
f.set(b.cObject, b); 
+0

appliqué: B $$ EnhancerByMockitoWithCGLIB $$ 999ce15d @ 7a187814 'c'est le point. Je l'ai vu dans la section montre d'Eclipse. Y a-t-il du travail pour cette situation? – iberbeu

+0

Malheureusement, je ne sais pas trop quoi suggérer - je dirais normalement passer dans l'objet espion mais ce n'est pas si facile dans ce cas. N'y a-t-il aucun moyen de casser la référence circulaire? – Jonathan

+0

il n'y a en fait aucun moyen de le casser parce que c'est du code hérité, donc j'ai juste besoin d'un moyen de le gérer. Et je ne peux pas passer l'objet mocké après l'avoir créé car il n'y a pas de méthode 'set' pour ça ... – iberbeu