web-dev-qa-db-fra.com

JUnit Test de variables privées?

On m'a confié la tâche de tester en classe une classe sur laquelle je n'ai jamais travaillé directement avec JUnit et il est formellement interdit de modifier le code contenu dans le paquet. Ce n’est généralement pas un problème, car la plupart de nos tests unitaires portent uniquement sur la cohérence des fonctionnalités et des entrées/sorties, ce qui peut être fait simplement en exécutant des routines et en vérifiant leurs valeurs de retour.

Cependant, il est parfois nécessaire de vérifier une variable privée dans la classe ou de modifier directement une variable privée pour vérifier un comportement interne. Existe-t-il un moyen d'y accéder, que ce soit via JUnit ou tout autre moyen, à des fins de test unitaire sans modifier réellement le code du package source d'origine? Et si non, comment les programmeurs gèrent-ils ce problème dans le monde réel où un testeur d'unité peut ne pas être la même personne que le codeur?

63
donnyton

Oui, vous pouvez utiliser les réflexions pour accéder aux variables privées. Ce n'est pas une bonne idée.

Regarde ça:

http://en.wikibooks.org/wiki/Java_Programming/Reflection/Accessing_Private_Features_with_Reflection

28
Alfredo Osorio

Tout d’abord, vous êtes maintenant dans une mauvaise position - vous avez pour tâche de rédiger des tests pour le code que vous n’avez pas créé à l’origine et sans aucune modification - cauchemar! Parlez à votre patron et expliquez-lui, il n'est pas possible de tester le code sans le rendre "testable". Pour rendre le code vérifiable, vous apportez généralement des modifications importantes.

En ce qui concerne les variables privées. En fait, vous ne devriez jamais faire cela. Vouloir tester des variables privées est le premier signe que quelque chose ne va pas avec la conception actuelle. Les variables privées font partie de la mise en œuvre, les tests doivent être axés sur le comportement plutôt que sur les détails de la mise en œuvre.

Parfois, les champs privés sont exposés à un accès public avec un getter. Je fais cela, mais essayez d'éviter autant que possible (marquez dans les commentaires, comme "utilisé pour les tests").

Étant donné que vous n'avez aucune possibilité de changer le code, je ne vois pas de possibilité (je parle d'une possibilité réelle, pas du genre réflexions, etc.) de vérifier une variable privée.

50
Alexander Beletsky

réflexion exemple:

public class PrivateObject {

  private String privateString = null;

  public PrivateObject(String privateString) {
    this.privateString = privateString;
  }
}
PrivateObject privateObject = new PrivateObject("The Private Value");

Field privateStringField = PrivateObject.class.
            getDeclaredField("privateString");

privateStringField.setAccessible(true);

String fieldValue = (String) privateStringField.get(privateObject);
System.out.println("fieldValue = " + fieldValue);
17
bpgergo

Malgré le danger de l'évidence: avec un test unitaire, vous voulez tester le comportement correct de l'objet - et ceci est défini en termes de son interface publique. Vous n'êtes pas intéressé par la manière dont l'objet accomplit cette tâche - il s'agit d'un détail d'implémentation non visible de l'extérieur. C’est l’une des raisons pour lesquelles OO a été inventé: les détails de la mise en œuvre sont cachés. Il n’est donc pas utile de tester les membres privés. Vous avez dit que vous aviez besoin d’une couverture à 100%. code qui ne peut pas être testé à l'aide de l'interface publique de l'objet, cette partie de code n'est en fait jamais appelée et, par conséquent, non testable.

3
MKK

Voici un article qui résout uniquement ce problème (impliquant spécifiquement des tests):

http://onjava.com/pub/a/onjava/2003/11/12/reflection.html

1
Joe0

Si vous créez vos classes de test dans un dossier séparé que vous ajoutez ensuite à votre chemin de construction,

Ensuite, vous pourriez faire de la classe de test une classe interne de la classe à tester en utilisant package correctement pour définir l'espace de noms. Cela lui donne accès à des champs et méthodes privés.

Mais n'oubliez pas de supprimer le dossier du chemin de génération de votre version finale.

0
Andrew p

Je ne peux pas dire si vous avez trouvé un code de cas spécial qui vous oblige à effectuer des tests sur des champs privés. Mais dans mon expérience, vous n'avez jamais à tester quelque chose de privé, toujours public Peut-être pourriez-vous donner un exemple de code dans lequel vous devez tester privé?

0
ThomasArdal