2010-10-14 3 views
4

J'essaie de se moquer d'une méthode d'un objet dans la classe que je suis en train de tester.JUnit moqueur avec Mockito, EasyMock, etc

Par exemple

class ClassToTest { 
    public doSomething() { 
     SomeObject a = new SomeObject(); 
     a.doSomethingElse(); 
    } 
} 

est-il un moyen de se moquer des méthodes de la variable "a"? Je voudrais faire quelque choseElse pour ne rien faire pendant les tests. J'utilise actuellement Mockito mais je suis ouvert à tout cadre moqueur.

Merci

Répondre

2

Oui, il existe un moyen, comme le montre le test JMockit suivant:

public void testDoSomething(final SomeObject mock) 
{ 
    new ClassToTest().doSomething(); 

    new Verifications() {{ mock.doSomethingElse(); }}; 
} 

Pas besoin de code de factoriser sous test utiliser un wrapper, DI, etc; simplement se moquer de tout ce dont vous avez besoin d'être moqué.

2

Il est impossible de se moquer de la référence « a » quand il est déclaré comme une variable locale, comme dans votre cas. Vous pouvez envisager d'injecter la dépendance dans SomeObject, par ex. en tant que paramètre de la méthode doSomething. De cette façon, vous pouvez injecter un faux de SomeObject dans votre test à la place.

Un des avantages de dependency injection is increased testability.

1

Je crois que vous pouvez utiliser EasyMock Class Extensions pour EasyMock 2.5 ou plus tôt, et apparemment il est inclus dans 3.0. Voir this part of the previous page pour plus d'informations sur ce que vous essayez de faire. Cela dit, je n'ai personnellement pas essayé de le faire, alors je ne sais pas si cela va marcher.

+0

Avec les extensions de classe EasyMock, vous pouvez simuler des classes dans lesquelles vous ne pouvez simuler que des interfaces sans extensions de classe. Cependant, vous ne pouvez pas simuler les références déclarées comme variables locales. –

2

Avec un peu de refactoring, il est possible, bien sûr:

class SomeObject { 
    public void doSomethingElse() 
    { 

    } 
} 

class ClassToTest 
{ 
    private final SomeObject someObject; 

    public void doSomething() 
    { 
     someObject.doSomethingElse(); 
    } 

    public ClassToTest(SomeObject someObject) 
    { 
     this.someObject = someObject; 
    } 
} 

class Test { 
    @Test 
    public void testDoSomething() 
    { 
     SomeObject someObject = Mockito.mock(SomeObject.class); 
     new ClassToTest(someObject).doSomething(); 
     Mockito.verify(someObject, Mockito.atLeastOnce()).doSomethingElse(); 
    } 
} 
+1

Oui, c'était aussi ma pensée. Je ne savais pas si je pouvais me moquer d'une variable locale (encore) – Shaun

0

Si vous voulez une nouvelle instance dans chaque appel, je vous suggère de refactoring de la manière suivante:

class ClassToTest { 
    public doSomething() { 
     SomeObject a = getInstance(); 
     a.doSomethingElse(); 
    } 
    protected SomeObject getInstance() { 
     return new SomeObject(); 
    } 
} 

Ensuite, vous peut créer une classe de test s'étendant ClassToTest, en remplaçant la méthode getInstance(), avec une méthode fournissant un objet fantaisie.

Ceci n'est bien sûr viable que si vous êtes autorisé à exposer la méthode getInstance(), donc je ne le recommande pas si la classe fait partie d'une API publique. Si c'est le cas, envisagez de fournir une classe de fabrique en utilisant l'injection de dépendance.

+0

Si vous allez sur cette route, je pense que je vais créer un fournisseur (Factory) et l'injecter. Un cadre DI décent (comme disent Guice) va créer l'usine pour vous. –

0
class ClassToTest { 
    private SomethingElseInterface somethingElseDoer ; 

    public ClassToTest(SomethingElseInterface somethingElseDoer) { 
     this.somethingElseDoer = somethingElseDoer; 
    } 

    public doSomething() { 
     somethingElseDoer.doSomethingElse(); 
    } 
} 

Et où vous l'utilisez:

SomethingElseInterface somethingElseDoer = ...; // in a test, this is where you mock it 
ClassToTest foo = new ClassToTest(somethingElseDoer); // inject through constructor 
foo.doSomething(); 
Questions connexes