Undeadparade
Undeadparade

Reputation: 1542

Any alternative for Microsoft Fakes in .NET Core?

I am looking for an alternative to Microsoft Fakes in .NET Core. I know it is no longer supported in .NET Core. I just do not understand why not, I think it was a good solution in certain situations.

My problem is that I want to mock DateTime.Now. Previously you could do this with the following code:

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

It is described in the Microsoft documentation, see the link for more information: https://learn.microsoft.com/en-us/visualstudio/test/using-shims-to-isolate-your-application-from-other-assemblies-for-unit-testing?view=vs-2017

For now I solved it by creating a wrapper for DateTime, which looks like this:

/// <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;
   }
}

I owe this solution to the next StackOverflow post: Unit Testing: DateTime.Now

But I am not satisfied with this solution yet, because I feel I have to adjust my implementation for my testing. I do not think this is desirable.

I hope someone can help me with this, thanks in advance for the effort.

Upvotes: 24

Views: 14500

Answers (4)

tb-mtg
tb-mtg

Reputation: 31

Poser is updated version 2 of the Pose NuGet package mentioned in Chris Gessler's answer

using Pose;

Shim dateTimeShim = Shim.Replace(() => DateTime.Now).With(() => new DateTime(2004, 4, 4));

Upvotes: 0

Francesco B.
Francesco B.

Reputation: 3097

I am looking for an alternative to Microsoft Fakes in .NET Core. I know it is no longer supported in .NET Core. I just do not understand why not, I think it was a good solution in certain situations.

Since May 19th 2020 Microsoft Fakes supports .NET Core.

https://learn.microsoft.com/en-us/visualstudio/releases/2019/release-notes#16.6.0

Upvotes: 5

Chris Gessler
Chris Gessler

Reputation: 23113

Pose works well for this.

using Pose;

Shim dateTimeShim = Shim.Replace(() => DateTime.Now).With(() => new DateTime(2004, 4, 4));

// This block executes immediately
PoseContext.Isolate(() =>
{
    // All code that executes within this block
    // is isolated and shimmed methods are replaced

    // Outputs "4/4/04 12:00:00 AM"
    Console.WriteLine(DateTime.Now);

}, dateTimeShim);

Upvotes: 11

Undeadparade
Undeadparade

Reputation: 1542

Thanks for all the comments, that certainly helped me. I have slightly modified my implementation;

The SystemTime class is now called DateTimeProvider and looks like this:

/// <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;
   }
}

I have chosen to make the setter private for Now(). As a result, a developer must explicitly use the method SetDateTime() to change the time. You can also choose to use a auto getter and setter property.

I also added an interface so that the class can be injected:

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

I hope that someone else will also benefit from this.

Upvotes: 2

Related Questions