81 votes

Tests unitaires en fonction du temps

J'ai besoin de tester une fonction dont le résultat dépend de l'heure actuelle (en utilisant les temps isBeforeNow() Joda).

     public boolean isAvailable() {
    return (this.someDate.isBeforeNow());
}
 

Est-il possible d'écraser / simuler l'heure système avec Mockito afin que je puisse tester la fonction de manière fiable?

142voto

Jon Skeet Points 692016

La meilleure façon (OMI) de rendre votre code testable est à extraire de la dépendance de "ce qui est à l'heure actuelle" dans sa propre interface, avec une mise en œuvre qui utilise l'heure actuelle du système (utilisé normalement) et une application qui vous permet de régler le temps, l'avance comme vous le souhaitez, etc.

J'ai utilisé cette approche dans diverses situations, et c'est bien travaillé. Il est facile à installer - il suffit de créer une interface (par exemple, Clock) qui est une méthode simple pour l'instant dans le format que vous souhaitez (par exemple à l'aide de Joda Temps, ou peut-être un Date).

65voto

Laurent Pireyn Points 3737

Joda time prend en charge la définition d'une "fausse" heure actuelle via les méthodes setCurrentMillisFixed et setCurrentMillisOffset de la classe DateTimeUtils .

Voir http://joda-time.sourceforge.net/api-release/org/joda/time/DateTimeUtils.html

1voto

Sergey Tachenov Points 8123

J'utilise une approche semblable à celle de Jon, mais au lieu de créer une interface spécialisée, juste pour le temps actuel (par exemple, Clock), j'ai l'habitude de créer un interface de test (par exemple, MockupFactory). J'y mets toutes les méthodes que j'ai besoin de tester le code. Par exemple, dans un de mes projets, j'ai quatre méthodes:

  • celui qui renvoie une maquette de la base de données client;
  • celui qui crée une maquette déclarant objet qui informe le code sur les changements dans la base de données;
  • celui qui crée une maquette de java.util.Minuterie qui exécute les tâches quand je le veux;
  • celui qui renvoie l'heure actuelle.

La classe testé a un constructeur qui accepte cette interface, entre autres arguments. Sans cet argument crée une instance par défaut de cette interface qui fonctionne "dans la vraie vie". À la fois l'interface et le constructeur colis privé, de sorte que le test de l'API n'y a pas de fuite à l'extérieur de l'emballage.

Si j'ai besoin de plus imité les objets, je viens d'ajouter une méthode à cette interface, et la mettre en œuvre dans les essais et les mises en production.

De cette façon, je code de conception appropriée pour le test, en premier lieu, sans imposer de trop sur le code lui-même. En fait, le code devient encore plus propre, car depuis, beaucoup de code usine est rassemblé en un seul endroit. Par exemple, si j'ai besoin de passer à un autre client de base de données mise en œuvre dans le code réel, je n'ai qu'à modifier une seule ligne au lieu de chercher les références du constructeur.

Bien sûr, tout comme dans le cas de Jon approche, il ne fonctionnera pas avec la 3e partie du code que vous sont pas en mesure ou n'est pas autorisé à modifier.

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