2014-09-17 5 views
0

Je veux tester cette méthode mais à l'intérieur de la méthode un nouvel objet est créé et ensuite une méthode de ce nouvel objet est appelée. Je veux sauter cela (cela implique de se connecter sur un serveur j2ee db qui ne m'intéresse pas). Comme un exemple simple, je veux juste vérifier que param1.logic() est appelé une fois, mais le test échoue parce que obj essaie de se connecter avec des informations d'identification que je ne veux pas prendre la peine d'entrer. Il n'y a aucun getters ou setters pour la variable obj Object2 privée, mais existe-t-il un moyen d'ignorer le constructeur et l'appel de connexion suivant?Mockito - Comment ignorer l'appel de méthode d'un objet membre privé?

public class Object1{ 

    private Object2 obj; 

    public void method(Object3 param1, String param2){ 
     //functionality 
     //logic to be tested 
     param1.logic(); 
     //end functionality 

     //how can I skip these two lines? 
     obj = new Object2(param1); 
     obj.logon(param2,param2,null, false); 
    } 
}  

Voici ce que j'ai essayé d'utiliser mais les méthodes dans obj.logon sont toujours appelées.

import static org.mockito.Mockito.mock; 
import static org.mockito.Mockito.spy; 
import static org.mockito.Mockito.when; 
import static org.mockito.Mockito.times; 
import static org.mockito.Mockito.verify; 

import org.mockito.Mockito; 
import org.mockito.invocation.InvocationOnMock; 
import org.mockito.stubbing.Answer; 
import org.powermock.api.mockito.PowerMockito; 

import org.junit.Before; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.powermock.core.classloader.annotations.PrepareForTest; 
import org.powermock.modules.junit4.PowerMockRunner;    

@RunWith(PowerMockRunner.class) 
@PrepareForTest(Object2.class) 
public class TestObject 
{ 
    @SuppressWarnings("unchecked") 
    @Before 
    public void init() throws Exception 
    { 
     var1 = mock(Object3.class) 
     obj2 = mock(Object2.class); 
     PowerMockito.whenNew(Object2.class).withAnyArguments().thenReturn(obj2); 
    } 

    @Test 
    public void testInvokeStandAloneJob() throws Exception 
    {   
     TestObject test = spy(new TestObject()); 
     Mockito.doAnswer(new Answer<Object>(){ 
      public Object answer(InvocationOnMock invocation){ 
       Object[] args = invocation.getArguments(); 
       return "called with arguments: " + args; 
      } 
     }).when(obj2).logon(Mockito.anyString(), Mockito.anyString(),Mockito.anyString(), Mockito.anyBoolean()); 
     //also tried doNothing 
     //Mockito.doNothing().when(obj2).logon(sDomainName, username,null, false); 

     //call method     
     test.method(var1, var2); 

     verify(var1,times(1)).logic(); 
    } 

Comment puis-je faire ces 2 lignes (le constructeur et la méthode suivante ne rien faire?)

+0

Rechercher dans la liaison du fournisseur de services Je ne suis pas sûr que cela va vous être utile, vous pouvez enchérir la classe obj avec un impl implicitement pour ce test. N'oubliez pas de supprimer les liaisons d'exécution. – StackFlowed

Répondre

1

Je crois que vous pouvez utiliser powermock pour simuler l'appel à new() et renvoyer un objet fantôme qui ne fait rien lorsque la méthode d'ouverture de session est appelée.

Avant d'utiliser PowerMock, assurez-vous de suivre les instructions sur cette page: https://code.google.com/p/powermock/wiki/MockConstructor

Plus précisément:

Assurez-vous d'ajouter ceci au début de votre classe de test

@RunWith(PowerMockRunner.class) 
@PrepareForTest(ClassThatCreatesTheNewInstance.class) 

Utilisez PowerMock.createMock (NewInstanceClass.class) pour créer un objet fantaisie de la classe qui doit être construite (appelons-le mockObject).

Vous pouvez également redéfinir votre classe pour ne pas utiliser le mot clé new dans cette méthode.(Sa mauvaise pratique de toute façon)

+0

Redesign to * not * utilise le mot clé 'new' dans cette méthode. –

+1

Vous êtes rapide, corrigé. – cowls

+0

Est-ce différent de PowerMockito.whenNew (Object2.class) .withAnyArguments(). ThenReturn (obj2); (bien que cela ne semble pas fonctionner) – irregular

0

Mocks sont excellent moyen de tester si vous suivez rigoureusement la dépendance modèle d'injection. Si vous ne le faites pas, les faux ne sont pas beaucoup d'aide.

Votre ligne ci-dessous

obj = new Object2(param1); 

est une violation de l'injection de dépendance.

Vous devez le remplacer par

obj = object2Factory.create() 

puis injecter object2Factory dans le constructeur ou comme une propriété.

MISE À JOUR:

Bien que je ne sais toujours pas comment se moquer du code original, je voudrais produire un refactoring alternatif.

Vous pouvez factoriser les lignes

obj = new Object2(param1); 
    obj.logon(param2,param2,null, false); 

dans leur propre méthode de package-privé:

Object2 createObject2(Object3 param1, String param2) { 
     Object2 o = new Object2(param1); 
     o.logon(param2,param2,null, false); 
     return o; 
} 

Vous pouvez ensuite utiliser spy() pour se moquer createObject2().

+0

et si je ne peux pas changer le code source de la méthode/classe que je suis en train de tester, que peut-on faire? – irregular

+1

Alors, quel est le point de test? Que faites-vous si vous trouvez un bug? – Arkadiy

+0

J'ai regardé de plus près votre code: ne pouvez-vous pas simplement tester 'param1.logic()' directement? – Arkadiy

Questions connexes