2017-09-29 6 views
0

J'ai une classe java - très typique du singleton habituel - comme ceci:Java singleton - Écrire un test unitaire pour la classe?

VEUILLEZ NOTER: J'ai omis la logique "if null" ici, par souci de concision, parce que ce n'est pas ce que je J'ai des problèmes avec, et je ne veux pas entasser la question.

public class MySingleton 
{ 
    ObjectMapper mapper; 

    private MySingleton() 
    { 
     new MySingleton(new ObjectMapper()) 
    } 

    private MySingleton(ObjectMapper mapper) 
    { 
     this.mapper = mapper; 
    } 

    private static final class Lazy 
    { 
     static final MySingleton INSTANCE = new MySingleton(); 
    } 

    public static MySingleton getInstance() 
    { 
     return Lazy.INSTANCE; 
    } 
} 

maintenant - ce qui est grand - et qui fonctionne - mais si je suis en train de tester cela dans un test unitaire ...

Je veux moquer cartographe - donc je peux faire:

ObjectMapper mockObjectMapper = mock(ObjectMapper.class) 

Mais, quand je dois appeler en quelque sorte le constructeur de « MySingleton » afin de le tester ...

Comment puis-je faire cela - étant donné que de ma classe de test, je sais que cela va dire "MySingleton (arguments ici) a p rivaliser l'accès à MySingleton "?

+2

Exactement quelles sont les exigences que vous essayez de tester? Je ne vois aucune logique dans l'une de ces méthodes qu'il serait logique de tester. Habituellement, essayer de tester des méthodes d'une ligne est une perte de temps complète. –

+0

"J'ai omis la logique" if null "ici" Si vous utilisez l'idiot de paresseux, vous ne devriez pas avoir besoin de logique "if null". –

+0

Regardez le framework PowerMock. – tsolakp

Répondre

0

Les singletons sont les ennemis du code testable. Les liens donnés dans la réponse à that question sont une excellente argumentation sur ce qui est mal avec les singletons ainsi que pourquoi et comment les éviter.

0

Vous pouvez utiliser PowerMock pour injecter votre instance ObjectMapper de test à l'aide de ConstructorMocking.

http://benkiefer.com/blog/2013/04/23/powermockito-constructor-mocking/

je devais modifier votre exemple singleton afin que les constructeurs ont été enchaînées correctement.

public class MySingleton { 
    ObjectMapper mapper; 

    private MySingleton() 
    { 
     //This does not work. 
     //new MySingleton(new ObjectMapper()); 

     this(new ObjectMapper()); 
    } 

    private MySingleton(ObjectMapper mapper) 
    { 
    this.mapper = mapper; 
    } 

    private static final class Lazy 
    { 
    static final MySingleton INSTANCE = new MySingleton(); 
    } 

    public static MySingleton getInstance() 
    { 
     return Lazy.INSTANCE; 
    } 
} 

J'ai également bloqué la classe ObjectMapper.

public class ObjectMapper { 
    //Empty Sample uses default CTR 
} 

j'ai pu tester cela comme suit en suivant les instructions du lien précédemment indiqué:

import org.junit.Assert; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.powermock.api.mockito.PowerMockito; 
import org.powermock.core.classloader.annotations.PrepareForTest; 
import org.powermock.modules.junit4.PowerMockRunner; 


@RunWith(PowerMockRunner.class) 
@PrepareForTest(MySingleton.class) 
public class MySingletonTest { 


    @Test 
    public void testSingletonCtr() throws Exception { 
     ObjectMapper mapper = new ObjectMapper(); 
     PowerMockito.whenNew(ObjectMapper.class).withNoArguments().thenReturn(mapper); 

     Assert.assertEquals(MySingleton.getInstance().mapper, mapper); 
    } 
} 

Je fais cela dans un projet Maven. Je avais besoin les dépendances suivantes ajoutées à mon champ d'essai:

<dependency> 
    <groupId>org.powermock</groupId> 
    <artifactId>powermock-core</artifactId> 
    <version>1.6.5</version> 
    <scope>test</scope> 
</dependency> 
<dependency> 
    <groupId>org.powermock</groupId> 
    <artifactId>powermock-module-junit4-rule</artifactId> 
    <version>1.6.5</version> 
    <scope>test</scope> 
</dependency> 
<dependency> 
    <groupId>org.powermock</groupId> 
    <artifactId>powermock-api-mockito</artifactId> 
    <version>1.6.5</version> 
    <scope>test</scope> 
</dependency> 

Je suis d'accord que singletons ont tendance à causer des problèmes à long terme pour la maintenance et l'évolutivité du code. Si vous avez la capacité de chercher d'autres solutions à votre problème, il peut vous être avantageux de le faire. Si non, alors je crois que l'utilitaire PowerMock vous fournira la capacité que vous recherchez.

Le meilleur de la chance.