annotation pour rendre une méthode privée publique uniquement pour les classes d'essai [dupliquer]

cette question a déjà une réponse ici:

qui a une solution pour ce besoin commun.

j'ai une classe dans ma demande.

certaines méthodes sont publiques, car ils font partie de l'api, et certains sont privés, comme ils pour usage interne de rendre le flux interne plus lisible

maintenant, disons que je veux écrire un test unitaire, ou plus comme un test d'intégration, qui sera situé dans un paquet différent, qui sera autorisé à appeler cette méthode, mais, je veux que l'appel normal à cette méthode ne sera pas autorisé si vous essayez de l'appeler à partir des classes de l'application elle-même

donc, je pensais à quelque chose comme ça

public class MyClass {

   public void somePublicMethod() {
    ....
   }

   @PublicForTests
   private void somePrivateMethod() {
    ....
   }
}

L'annotation ci-dessus indiquera que la méthode privée est "publique pour les essais" ce qui signifie que la compilation et l'exécution seront autorisées pour toute classe qui est sous le test... package, tandis que la compilation etou l'exécution échoueront pour toute classe qui n'est pas sous le package test.

une idée? est-il une annotation comme ça? est-il une meilleure façon de le faire?

il semble que plus vous écrivez de tests unitaires, plus vous êtes forcé de briser votre encapsulation...

69
demandé sur Kumetix 2011-08-02 18:02:39

12 réponses

la méthode habituelle consiste à protéger la méthode privée ou le colis-privé et à placer l'épreuve unitaire pour cette méthode dans le même colis que celui de la classe à l'essai. La goyave a une @VisibleForTesting annotation , mais c'est seulement pour la documentation.

107
répondu JB Nizet 2016-06-15 11:42:45

si votre couverture de test est bonne sur toute la méthode publique à l'intérieur de la classe testée, les méthodes privées appelées par le public Un seront automatiquement testées puisque vous allez affirmer tous les cas possibles.

JUnit Doc a dit:

L'essai de méthodes privées peut indiquer que ces méthodes devraient être déplacées dans une autre classe pour favoriser la réutilisation. Mais si vous devez... Si vous utilisez JDK 1.3 ou plus, vous pouvez utiliser réflexion pour subvertir le mécanisme de contrôle d'accès à l'aide de L'accès privilégié. Pour plus de détails sur la façon de l'utiliser, lire cet article.

18
répondu Cygnusx1 2011-08-02 14:34:33

envisager d'utiliser des interfaces pour exposer les méthodes API, en utilisant des usines ou DI pour publier les objets afin que les consommateurs les connaissent seulement par l'interface. L'interface décrit l'API publiée. De cette façon, vous pouvez rendre public ce que vous voulez sur les objets de mise en œuvre et les consommateurs ne voient que ces méthodes exposées à travers l'interface.

10
répondu Nathan Hughes 2016-01-25 19:17:20

dp4j a ce dont vous avez besoin. Essentiellement, tout ce que vous avez à faire est d'ajouter dp4j à votre chemin de classe et chaque fois qu'une méthode annotée avec @Test (annotation de JUnit) appelle une méthode qui est privée, cela fonctionnera (dp4j injectera la réflexion requise au moment de la compilation). Vous pouvez également utiliser l'annotation @TestPrivates de dp4j pour être plus explicite.

si vous insistez sur l'annotation de vos méthodes privées, vous pouvez utiliser L'annotation @VisibleForTesting de Google.

4
répondu simpatico 2012-05-17 18:59:29

un article sur Testing Private Methods expose certaines approches pour tester le code privé. utiliser la réflexion impose un fardeau supplémentaire au programmeur pour se rappeler si le remaniement est fait, les chaînes ne sont pas changées automatiquement, mais je pense que c'est l'approche la plus propre.

3
répondu Atreys 2011-08-02 14:12:06

ou vous pouvez extraire cette méthode à quelque stratégie objet. Dans ce cas, vous pouvez facilement tester la classe extraite et ne pas rendre la méthode publique ou quelque magie avec reflection/bytecode.

2
répondu Stan Kurilin 2011-08-02 14:37:38

Je ne suis pas au courant d'une telle annotation, mais les éléments suivants peuvent être utiles: unit testing private methods

ou la mention suivante: JMockit

1
répondu Woot4Moo 2017-05-23 12:26:00

vous ne pouvez pas faire ça, depuis, comment avez-vous pu compiler vos tests? Le compilateur ne pas prendre en compte la propriété.

il y a deux approches générales à cette

La première consiste à utiliser la réflexion pour accéder aux méthodes de toute façon

la seconde est d'utiliser package-private au lieu de private, puis avoir vos tests dans le même package (mais dans un module différent). Ils seront essentiellement privés à d'autres codes, mais vos tests pourront toujours y accéder.

bien sûr, si vous faites des tests de boîte noire, vous ne devriez pas accéder aux membres privés de toute façon.

1
répondu Joeri Hendrickx 2011-08-02 14:17:43

nous avons récemment publié une bibliothèque qui aide beaucoup à accéder aux champs privés, méthodes et classes intérieures par la réflexion : BoundBox

pour une classe comme

public class Outer {
    private static class Inner {
        private int foo() {return 2;}
    }
}

il fournit une syntaxe comme:

Outer outer = new Outer();
Object inner = BoundBoxOfOuter.boundBox_new_Inner();
new BoundBoxOfOuter.BoundBoxOfInner(inner).foo();

la seule chose que vous devez faire pour créer la classe BoundBox est d'écrire @BoundBox(boundClass=Outer.class) et la classe BoundBoxOfOuter sera générée instantanément.

1
répondu Snicolas 2013-10-07 11:15:39

Ok, donc ici nous avons deux choses qui sont mélangées. Tout d'abord, quand vous avez besoin de marquer quelque chose pour être utilisé seulement sur le test, ce que je suis d'accord avec @JB Nizet, en utilisant l'annotation de goyave serait bon.

Une autre chose, est de tester des méthodes privées. Pourquoi tester des méthodes privées de l'extérieur? Je veux dire.. Vous devriez être en mesure de tester l'objet par leurs méthodes, et à la fin que son comportement. Au moins, que nous faisons et essayons d'apprendre à les développeurs juniors, qui essaient toujours de tester des méthodes privées (comme une bonne pratique).

1
répondu facundofarias 2015-01-19 10:46:36

autant que je sache il n'y a pas d'annotation de ce genre. La meilleure façon est d'utiliser la réflexion comme certains l'ont suggéré. Regardez ce billet:

Comment puis-je tester une classe qui a des méthodes privées, des champs ou des classes intérieures?

vous ne devez faire attention sur l'essai de l'exception résultat de la méthode. Par exemple: si u s'attend à une interception ArgumentException illégale, mais à la place vous obtiendrez "null"" (Classe:java.lang.refléter.InvocationTargetException).

Une de mes collègues a proposé d'utiliser le powermock framework pour ces situations, mais je ne l'ai pas encore testé, donc aucune idée de ce qu'il peut faire exactement. Bien que j'ai utilisé le cadre de Mockito qu'il est basé sur et thats un bon cadre aussi (mais je pense ne résout pas la question de l'exception de la méthode privée).

c'est une bonne idée bien que d'avoir les annotation.

santé!

0
répondu despot 2017-05-23 12:02:20

je viens de mettre le test dans la classe elle-même en faisant une classe intérieure: http://www.ninthavenue.com.au/how-to-unit-test-private-methods

0
répondu Roger Keays 2013-04-14 19:51:33