10 votes

Outil Java pour tester les méthodes privées ?

Les avis divergent quant à l'utilité des tests des méthodes privées, par exemple, aquí y aquí . Personnellement, je pense que c'est logique, la question est de savoir comment le faire correctement. En C++, vous pouvez utiliser un #define piratage ou faire de la classe de test friend en C#, il y a la fonction InternalsVisibleToAttribute mais en Java, nous devons soit utiliser réflexion ou de les rendre "visibles pour les tests" et les annoter comme suit afin de clarifier l'intention. Les inconvénients de l'un et de l'autre devraient être clairs.

Je pense qu'il devrait y avoir quelque chose de mieux. En commençant par

public class Something {
    private int internalSecret() {
        return 43;
    }
}

il serait intéressant de pouvoir appeler des méthodes privées dans le code de test, par exemple

@MakeVisibleForTesting Something something = new Something();
Assert.assertEquals(43, something.internalSecret());

Ici, l'annotation convertirait silencieusement tous les appels aux méthodes privées de something l'utilisation de la réflexion. Je me demande si Lombok pourrait le faire (et le demandera aux auteurs).

Il est tout à fait possible que faire autant de magie s'avère trop compliqué, et dans tous les cas cela prendra du temps, donc je cherche une alternative. Peut-être en annotant la classe testée avec quelque chose comme @Decapsulate et en utilisant un processeur d'annotation pour générer une classe Decapsulated_Something à l'image de

public class Decapsulated_Something {
    public Decapsulated_Something(Something delegate) {
        this.delegate = delegate
    }
    public boolean internalSecret() {
        // call "delegate.internalSecret()" using reflection
    }
    ...
}

ce qui permettrait d'utiliser

Decapsulated_Something something = new Decapsulated_Something(new Something());
Assert.assertEquals(43, something.internalSecret());

Je n'ai pas beaucoup d'expérience en matière de traitement des annotations, c'est pourquoi je demande d'abord ici :

  • Dans quelle mesure la mise en œuvre est-elle compliquée ?
  • Qu'ai-je oublié ?
  • Qu'en pensez-vous d'une manière générale ?

7voto

Alex Gitelman Points 15062

Il semble que cette mise en œuvre pose beaucoup de problèmes. Cela n'en vaut peut-être pas la peine. Il est préférable d'utiliser la méthode par défaut.

Toutefois, si vous êtes déterminé à appeler une méthode privée, vous pouvez utiliser l'option setAccessible dans votre Decapsulated_something pour permettre l'appel par réflexion. C'est donc assez simple.

2voto

Peter Lawrey Points 229686

Il existe un certain nombre d'approches

  • Ne testez pas les méthodes privées, car elles cachent des détails d'implémentation qui ne devraient jamais faire de différence pour l'appelant.
  • Rendez le paquetage des méthodes local afin qu'un appelant ne puisse pas y accéder, mais vous pouvez y accéder dans le même paquetage, c'est-à-dire dans un test unitaire.
  • Faire du test unitaire une classe interne ou fournir une classe interne locale au paquet. Pas sûr qu'il s'agisse d'une amélioration !
  • Utiliser la réflexion pour accéder aux méthodes de la classe. Cela équivaut à marquer une méthode comme étant privée de réflexion alors qu'elle ne l'est pas, et c'est une confusion, selon moi. Vous ne devriez marquer une méthode comme privée que lorsqu'elle l'est réellement.

2voto

simpatico Points 2730

il serait intéressant de pouvoir appeler des méthodes privées dans le code de test comme

@MakeVisibleForTesting Something something = new Something();
Assert.assertEquals(43, something.internalSecret());

Il existe une méthode d'annotation. dp4j 's @TestPrivates :

@Test
@TestPrivates 
//since the method is annotated with JUnit's @Test this annotation is redundant. 
// You just need to have dp4j on the classpath.
    public void somethingTest(){
      Something something = new Something();
      int sthSecret = something.internalSecret();
       Assert.assertEquals(43, sthSecret); //cannot use something.internalSecret() directly because of bug [dp4j-13][2] 
    }

1voto

drekka Points 10020

Je répondrai à la question "En général" :-) Il suffit de quelques lignes de code pour rendre une méthode accessible par réflexion et il existe un grand nombre de bibliothèques, d'utilitaires, d'API, etc. qui fournissent des méthodes pour le faire. Il y a aussi probablement beaucoup de techniques différentes que vous pourriez utiliser dans votre propre code. Par exemple, la manipulation du bytecode, la réflexion, les extensions de classe, etc. Mais je serais enclin à garder les choses simples. Bien qu'il puisse être utile de tester les méthodes privées, il est également probable que vous ne souhaitiez en tester que quelques-unes. Donc, concevoir quelque chose de complexe est probablement exagéré. Je me contenterais d'utiliser une API établie, ou d'écrire une méthode rapide pour accéder aux méthodes privées qui m'intéressent, et je m'en tiendrais là.

1voto

prunge Points 8131

Il y a quelques années, j'ai travaillé sur un projet qui générait des classes pour faciliter le test unitaire des méthodes privées. http://java.net/projects/privateer/

Il génère des classes supplémentaires qui facilitent l'appel à la réflexion, par exemple, si vous avez MyClass.myPrivateMethod(), il génère une classe _MyClass qui permet l'invocation de myPrivateMethod directement.

Il n'a jamais été vraiment terminé et s'est avéré utile dans certains cas, mais dans l'ensemble, je ne recommanderais pas de tester les méthodes privées à moins que cela ne soit absolument nécessaire. En général, les transformer en classes utilitaires (avec un accès au paquetage si vous êtes inquiet que des utilisateurs les utilisent) est une meilleure option.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X