7
votes

Comment accéder à un fichier de test de test (Java)?

Je sais qu'un bon test unitaire ne doit jamais accéder au système de fichiers. Donc, je sais aussi que vous pouvez utiliser Mockito et PowerMock, par exemple pour se moquer de la classe de fichiers.

Mais qu'en est-il du code suivant: xxx

Cette classe initiale Attribut de TOC avec le contenu du fichier situé à TOCRESOURCE.

La première chose qui me vient à l'esprit pour le test consiste à créer une classe de sous-classe qui n'appelle pas super dans le constructeur, donc tout l'accès au fichier n'est pas fait. Dans mon propre constructeur, je insère des données factices test pour les données qui auraient dû être lues à partir du fichier. Ensuite, je peux tester le reste de la classe sans problème.

Cependant, le code de constructeur de la classe d'origine n'est pas testé du tout. Et s'il y a une erreur?


2 commentaires

Vous ne pouvez pas éviter d'appeler le constructeur de superclasse. Si vous n'appelez pas explicitement cela, le compilateur essaie de générer un appel au constructeur par défaut zéro argument. Si cela n'existe pas, c'est une erreur de compilation.


Il serait possible de créer un constructeur par défaut de l'argument zéro dans la classe d'origine qui ne fait que rien. Ou on pourrait utiliser PowerMocks Whitebox.Newinstance.


5 Réponses :


3
votes

Où avez-vous eu l'idée qu'un "bon" test unitaire ne doit pas accéder au système de fichiers? Il n'y a rien de mal à cela, tant que le test est reproductible dans plusieurs environnements. Donc, dans ce cas, cela signifie que vous créez un fichier statique sur le parcours de test et vous transmettez le chemin de ce fichier sur le constructeur ClassLoaderProductDataProvider. Pas besoin de le rendre plus compliqué.


5 commentaires

Eh bien, vous pouvez le lire presque partout si vous Google "Bon test d'unité" ou "Meilleures pratices de test unitaire". De plus, il fait des tests d'unités considérablement plus lents, ce qui est mauvais pour TDD. Vous pouvez utiliser IoExceptions à tout moment (par exemple, lorsque les tests sont exécutés sur un autre serveur sans autorisations nécessaires). Vous pouvez rencontrer des problèmes si vous comptez qu'un fichier n'est pas là, vous pouvez donc le créer, mais l'ancien test de test n'a pas supprimé le fichier ...


Le système de fichiers est une dépendance externe qui, par de nombreuses définitions du test d'unité, effectue un test qui en dépend un test d'intégration de quelque sorte. Éviter l'accès du système de fichiers Dans les tests de l'unité que vous exécutez tout le temps pendant le développement les rend exécutions plus rapides et élimine une source possible de défaillances de test qui ne sont pas réellement liées à la classe testée. Bien sûr, si vous voulez dire «tests automatisés» par des tests unitaires, c'est une histoire différente.


@ user519499: si le fichier de test fait partie de l'arborescence source, il ne devrait pas y avoir de problèmes d'autorisation (s'il y a des problèmes plus gros.) Et si vous avez des problèmes avec des fichiers qui n'ont pas été nettoyés Juste, nettoyez-les avant le test. @Colind: L'argument "L'unité" vs "intégration" est totalement inutile, à mon avis. En tant que développeur, je suis payé pour vous assurer que le code fonctionne - je n'ai pas le temps de scinder les cheveux.


Quoi qu'il en soit, tout est à côté du point. Lecture du système de fichiers est ce que ce code fait : il n'y a pas de bon moyen de le tester sans accéder au système de fichiers.


Ce code ne devrait pas besoin pour lire le système de fichiers ... Il a d'autres responsabilités qui doivent être testables indépendantes du système de fichiers. L'accès du système de fichiers peut être poussé ailleurs, dans une classe plus petite qui vient vraiment de lire le système de fichiers, facilitant ainsi les tests de cette classe et éventuellement d'autres aussi.



4
votes

L'accès au système de fichiers est parfaitement acceptable pour les tests d'unités. En fait, il est assez courant d'avoir toute une suite de fichiers que vous utilisez comme des luminaires pour un système sous test. Cela facilite l'ajout de nouveaux tests car vous n'avez pas besoin d'ajouter un nouveau code, juste des données.


1 commentaires

+10! Je ne comprends pas la nécessité de scinder les cheveux sur la terminologie. J'utilise cette technique assez souvent. Si quelqu'un veut me forcer à appeler cela un "test d'intégration", c'est bien, tant que cela n'est pas mis dans le même camp que ceux qui interagissent avec la base de données ou d'autres éléments qui ne sont pas disponibles 99,999% du temps système de fichiers est.



2
votes

Vous pouvez passer dans un chargeur de classe personnalisé qui fournit une instance de test de TOCURL lorsqu'elle est appelée. Cependant, pourquoi passer du tout dans le chargeur de classe? Si tout ce que vous utilisez est le TOCURL, passez simplement cela au lieu du chargeur de classe et du talon. Cela simplifie grandement les choses.

public ClassLoaderProductDataProvider(ClassOfToUrl tocUrl, String tocResourcePath, boolean checkTocModifications) {
// ...
this.tocUrl = tocUrl;


0 commentaires

9
votes

Voici la chose: Généralement, pour effectuer des travaux de test d'unités appropriés, vous devez fournir à vos classes avec interfaces plutôt que des classes concrètes pour vous permettre de faire une flexibilité dans différentes choses pour les tests. En regardant votre exemple, il me semble que vous devriez extraire la responsabilité de charger un document à une autre classe ... avec une interface appelée documentsource , dites.

Ensuite, votre code ne dépendrait pas du tout du système de fichiers. Il pourrait ressembler à quelque chose comme xxx

alternativement, vous pouvez avoir la classe à prendre un document ou même un introuvable directement dans son constructeur. Bien sûr, à un moment donné, vous devez avoir le code réel qui charge le INPUTREAM de la ressource à l'aide du chargeur de classes ... mais vous pouvez pousser ce code dans quelque chose de simple que seulement cela. Ensuite, il est clair que tout test que vous faites de que la classe doit utiliser un fichier réel ... mais le test d'autres classes n'est pas affecté.

comme une note latérale, c'est un Mauvais signe pour la testabilité d'une classe si elle fonctionne (comme le chargement de la table des matières dans ce cas) dans son constructeur. Il y a probablement un moyen bien meilleur de concevoir les classes impliquées ici qui élimine le besoin de cela et est plus testable, mais il est difficile de dire exactement ce que cette conception est donnée juste ceci.

Il y a diverses autres options Pour ce que vous pouviez faire aussi, y compris l'utilisation de quelque chose comme de Guava INPUTSUPPLIER Interface associée à une méthode d'usine déjà testée comme ressources.newinputtreamsupplier (URL) pour obtenir le INPUTSUPPLIER instance d'utilisation en production. La chose essentielle, cependant, est de toujours avoir vos cours dépendent des interfaces afin de pouvoir utiliser facilement des implémentations alternatives dans les tests.


0 commentaires

2
votes

Le test unitaire n'est qu'un seul outil de votre sac à outils de test. Mais comme tous les outils, il a un but destiné et un champ d'application limité. L'art du test de l'unité de Roy Osherove expliquerait que les tests d'unités sont un mauvais ajustement lorsque des dépendances externes sont impliquées. C'est pour des raisons qui ont été indiquées ailleurs dans cette question: maintenir le test de test rapide, effectuer des tests répétables dans les environnements de développeurs, éliminant les fausses échecs de test, etc.

Lecture du système de fichiers, même si c'est un travail intégré d'un code de code, est une telle dépendance externe. Donc, il me semble que vous essayez de forcer cette situation à être unitaire, quand ce n'est vraiment pas. Vous devriez tester un appareil à tester ce que vous pouvez - en utilisant des bibliothèques simulées et une bonne conception découplée - et utilisez d'autres outils de test tels que des tests d'intégration manuelle ou automatisés pour tester des dépendances externes.


0 commentaires