web-dev-qa-db-fra.com

Une alternative pour Microsoft Fakes dans .NET Core?

Je recherche une alternative à Microsoft Fakes dans .NET Core. Je sais qu'il n'est plus pris en charge dans .NET Core. Je ne comprends tout simplement pas pourquoi, je pense que c'était une bonne solution dans certaines situations.

Mon problème est que je veux me moquer de DateTime.Now. Auparavant, vous pouviez le faire avec le code suivant:

System.Fakes.ShimDateTime.NowGet = () => 
{ 
   return new DateTime(2000, 1, 1); 
};

Il est décrit dans la documentation Microsoft. Pour plus d'informations, consultez le lien correspondant: https://docs.Microsoft.com/en-us/visualstudio/test/using-shims-to-isolate-your-application-from-other -assemblies-for-unit-testing? view = vs-2017

Pour l'instant je l'ai résolu en créant un wrapper pour DateTime, qui ressemble à ceci:

/// <summary>
/// Used for getting DateTime.Now(), time is changeable for unit testing
/// </summary>
public static class SystemTime
{
   /// <summary> 
   /// Normally this is a pass-through to DateTime.Now, but it can be 
   /// overridden with SetDateTime( .. ) for testing or debugging.
   /// </summary>
   public static Func<DateTime> Now = () => DateTime.Now;

   /// <summary> 
   /// Set time to return when SystemTime.Now() is called.
   /// </summary>
   public static void SetDateTime(DateTime dateTimeNow)
   {
      Now = () =>  dateTimeNow;
   }

   /// <summary> 
   /// Resets SystemTime.Now() to return DateTime.Now.
   /// </summary>
   public static void ResetDateTime()
   {
       Now = () => DateTime.Now;
   }
}

Je dois cette solution à la prochaine publication StackOverflow: Unit Testing: DateTime.Now

Mais je ne suis pas encore satisfait de cette solution car je sens que je dois ajuster mon implémentation pour mes tests. Je ne pense pas que ce soit souhaitable.

J'espère que quelqu'un pourra m'aider avec cela, merci d'avance pour l'effort.

4
Undeadparade

Merci pour tous les commentaires, cela m'a certainement aidé. J'ai légèrement modifié mon implémentation;

La classe SystemTime s'appelle maintenant DateTimeProvider et ressemble à ceci:

/// <summary>
/// Used for getting DateTime.Now(), time is changeable for unit testing
/// </summary>
public class DateTimeProvider : IDateTimeProvider
{
   /// <summary> 
   /// Normally this is a pass-through to DateTime.Now, but it can be 
   /// overridden with SetDateTime( .. ) for testing or debugging.
   /// </summary>
   private Func<DateTime> _now = () => DateTime.Now;
   public Func<DateTime> Now { get => _now; private set => _now = value; }

   /// <summary> 
   /// Set time to return when DateTimeProvider.Now() is called.
   /// </summary>
   public void SetDateTime(DateTime dateTimeNow)
   {
      Now = () =>  dateTimeNow;
   }

   /// <summary> 
   /// Resets DateTimeProvider.Now() to return DateTime.Now.
   /// </summary>
   public void ResetDateTime()
   {
       Now = () => DateTime.Now;
   }
}

J'ai choisi de rendre privé le setter pour Now (). Par conséquent, un développeur doit explicitement utiliser la méthode SetDateTime () pour modifier l'heure. Vous pouvez également choisir d’utiliser une propriété de getter et de setter automatique.

J'ai aussi ajouté une interface pour que la classe puisse être injectée:

public interface IDateTimeProvider
{
    Func<DateTime> Now { get; }
    void SetDateTime(DateTime dateTimeNow);
    void ResetDateTime();
}

J'espère que quelqu'un d'autre en profitera également.

1
Undeadparade