Ce qui est un bon moyen de remplacer le type DateTime.Maintenant, pendant les tests?
J'ai quelques (C#), le code qui s'appuie sur la date d'aujourd'hui pour calculer correctement les choses à l'avenir. Si j'utilise la date du jour dans le test, je dois refaire le calcul dans le test, qui ne se sent pas bien. Quelle est la meilleure façon de fixer la date d'une valeur connue au sein de l'épreuve, afin que je puisse le tester, le résultat est une valeur connue?
Vous devez vous connecter pour publier un commentaire.
Ma préférence est d'avoir des classes qui utilisent le temps de réellement s'appuyer sur une interface, comme
Avec une mise en œuvre concrète
Ensuite, si vous le souhaitez, vous pouvez fournir tout autre type d'horloge que vous voulez pour les tests, tels que
Il peut y avoir des frais généraux dans la fourniture de l'horloge de la classe qui s'appuie sur elle, mais qui pourrait être prise en charge par un certain nombre de l'injection de dépendance des solutions (à l'aide d'une Inversion de Contrôle conteneur, plaine ancien constructeur/définition d'injection, ou même un Passerelle Statique Modèle).
D'autres mécanismes de la prestation d'un objet ou d'une méthode qui offre des moments voulus aussi travailler, mais je pense que la clé, c'est pour éviter la réinitialisation de l'horloge du système, qui va juste pour introduire de la douleur à d'autres niveaux.
Également, à l'aide de
DateTime.Now
et de l'inclure dans vos calculs, n'est pas seulement de ne pas se sentir le droit - il vous prive de la possibilité de tester des moments particuliers, par exemple si vous découvrez un bug qui n'arrive près de minuit limite, ou sur les les mardis. Utilisez l'heure actuelle ne vous permet pas de tester ces scénarios. Ou du moins, pas quand vous le voulez.UtcNow
doit être utilisé et ensuite ajusté de manière appropriée en fonction de la préoccupation du code, de l'e.g une logique d'entreprise, INTERFACE, etc. DateTime manipulation à travers les fuseaux horaires est un champ de mines, mais le meilleur premier pied vers l'avant, est de toujours commencer avec l'heure UTC.Ayende Rahien utilise une méthode statique qui est plutôt simple...
Je pense que créer un classe de l'horloge pour quelque chose de simple comme obtenir la date du jour est un peu exagéré.
Vous pouvez passer à la date d'aujourd'hui en tant que paramètre de sorte que vous pouvez entrer une date dans le test. Ceci a l'avantage supplémentaire de rendre votre code plus souple.
À l'aide de Microsoft Faux pour créer une cale est vraiment un moyen facile de le faire. Supposons que j'avais la classe suivante:
Dans Visual Studio 2012, vous pouvez ajouter un Faux montage de votre projet de test en cliquant à droite sur le montage que vous voulez pour créer des Fakes/Cales pour et en sélectionnant "Ajouter des Faux Assemblée"
Enfin, Voici ce que la classe de test ressemblerait à:
La clé de la réussite de tests unitaires est découplage. Vous devez séparer votre intéressante code à partir de ses dépendances externes, de sorte qu'il peut être testé dans l'isolement. (Heureusement, Développement Piloté par les tests produit découplé code.)
Dans ce cas, votre externe est l'actuel DateTime.
Mon conseil ici est d'extraire de la logique qui traite de la date d'une nouvelle méthode ou une classe ou tout ce qui fait sens dans votre cas, et de passer le DateTime dans. Maintenant, votre unité de test peut passer à l'arbitraire d'un DateTime en, à produire des résultats prévisibles.
Un autre à l'aide de Microsoft Moles (L'isolement cadre .NET).
Je suggérerais à l'aide de IDisposable modèle:
Décrit en détail ici:
http://www.lesnikowski.com/blog/index.php/testing-datetime-now/
Réponse Simple: Système de fossé.DateTime 🙂 au Lieu de cela, utiliser NodaTime et tests de la bibliothèque: NodaTime.Les tests.
Pour en savoir plus:
Vous pourrait injecter de la classe (mieux: méthode/délégué) que vous utilisez pour
DateTime.Now
dans la classe en cours d'essai. OntDateTime.Now
être une valeur par défaut et ne réglez-le en test à un mannequin de la méthode qui retourne une valeur constante.EDIT: Ce que Blair Conrad a dit (il a un peu de code pour les voir). Sauf, j'ai tendance à préférer les délégués pour cela, que de ne pas encombrer votre hiérarchie de classe avec des trucs comme
IClock
...J'ai fait face à cette situation, si souvent, que j'ai créé simple nuget qui expose Maintenant propriété par le biais de l'interface.
Mise en œuvre est très simple
Ainsi, après l'ajout de nuget pour mon projet je peux l'utiliser dans les tests unitaires
Vous pouvez installer le module à droite de l'interface graphique Gestionnaire de Package Nuget ou à l'aide de la commande:
Et le code de la Nuget est ici.
L'exemple de l'utilisation de l'Autofac peut être trouvé ici.
Avez-vous envisagé d'utiliser la compilation conditionnelle pour contrôler ce qui se passe au cours de debug/déploiement?
par exemple
À défaut, vous souhaitez exposer la propriété de sorte que vous pouvez le manipuler, c'est toute la partie du défi de l'écriture testable code, qui est quelque chose que je suis actuellement à la lutte moi-même 😀
Modifier
Une grande partie de moi serait de préférence Blair approche. Cela vous permet de "hot plug" parties du code à l'aide de tests. Tout cela suit le principe de conception encapsuler ce qui varie, code de test n'est pas différent de la production de code, c'est juste que on ne les voit jamais à l'extérieur.
La création et l'interface peut sembler comme beaucoup de travail pour cet exemple (c'est pourquoi j'ai opté pour la compilation conditionnelle).
DateTime
'sNow
etToday
etc.