Есть ли альтернатива Microsoft Fakes в .NET Core?

Я ищу альтернативу Microsoft Fakes в .NET Core. Я знаю, что это больше не поддерживается в .NET Core. Я просто не понимаю, почему нет, я считаю, что это было хорошее решение в определенных ситуациях.

Моя проблема в том, что я хочу издеваться над DateTime.Now. Раньше это можно было сделать с помощью следующего кода:

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

Это описано в документации Microsoft, см. Ссылку для получения дополнительной информации: https://docs.microsoft.com/en-us/visualstudio/test/using-shims-to-isolate-your-application-from-other-assemblies-for-unit-testing?view=vs-2017

На данный момент я решил это, создав оболочку для DateTime, которая выглядит так:

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

Этим решением я обязан следующему сообщению на StackOverflow: Модульное тестирование: DateTime.Now

Но я пока не удовлетворен этим решением, потому что чувствую, что должен скорректировать свою реализацию для моего тестирования. Я не думаю, что это желательно.

Надеюсь, кто-нибудь сможет мне с этим помочь, заранее спасибо за усилия.


person Undeadparade    schedule 25.09.2018    source источник
comment
Это очень хорошее решение. Этот макет понадобится вам также при ручном тестировании или в процессе производства, когда вам нужно будет иметь текущее время, отличное от времени, установленного в ОС.   -  person TcKs    schedule 25.09.2018
comment
Фактически вы улучшаете реализацию, делая зависимость от DateTime.Now явной (которая, как я полагаю, была скрытой зависимостью)   -  person Lennart Stoop    schedule 25.09.2018
comment
Правильный способ для любой системы, платформы, языка программирования и т. Д. Состоит в том, чтобы фактически удалить жесткую зависимость от DateTime.Now (или эквивалента, если это другая система, платформа и т. Д.), Чтобы вы могли внедрить его. Скрытые зависимости - бич тестирования, потому что ... ну ... они скрыты, т.е. они не видны вам, поэтому их слишком легко пропустить и не заметить при настройке новых сценариев тестирования. Чтобы вы фактически поместили ее за абстракцию, которую затем нужно внедрить (что вы также должны сделать), делает эту зависимость видимой и, следовательно, более простой в обращении.   -  person Lasse V. Karlsen    schedule 25.09.2018
comment
Вместо того, чтобы использовать static, я бы (как и Лассе) обычно реализовал это как DateTimeProvider : IDateTimeProvider. Тогда ваши классы имеют явную зависимость от IDateTimeProvider. Это делает кристально ясным, какие классы зависят от DateTime, и, следовательно, над ними нужно высмеивать. Обратной стороной использования static с точки зрения модульного тестирования является то, что ваши тесты не могут быть распараллелены (поскольку существует только одно значение static, поэтому, если разные тесты хотят моделировать разные значения, они будут давить друг на друга).   -  person mjwills    schedule 25.09.2018
comment
Это в их дорожной карте. См. developercommunity.visualstudio.com/idea/351467 /.   -  person Mike Lowery    schedule 31.05.2019


Ответы (3)


Я ищу альтернативу Microsoft Fakes в .NET Core. Я знаю, что это больше не поддерживается в .NET Core. Я просто не понимаю, почему нет, я считаю, что это было хорошее решение в определенных ситуациях.

С 19 мая 2020 года Microsoft Fakes поддерживает .NET Core.

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

person Francesco B.    schedule 19.05.2020
comment
Он доступен только для пользователей Visual Studio Enterprise, думающих - person Antoine L; 29.01.2021
comment
Я видел это сейчас, да - person Francesco B.; 01.02.2021

Для этого хорошо подходит поза.

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);
person Chris Gessler    schedule 05.05.2019
comment
Кажется, что это бомба всякий раз, когда есть вызов метода Async. github.com/tonerdo/pose/issues/25 - person Brian Colavito; 25.02.2020

Спасибо за все комментарии, которые, безусловно, мне помогли. Я немного изменил свою реализацию;

Класс SystemTime теперь называется DateTimeProvider и выглядит так:

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

Я решил сделать установщик приватным на данный момент (). В результате разработчик должен явно использовать метод SetDateTime () для изменения времени. Вы также можете использовать свойство автоматического получения и установки.

Я также добавил интерфейс, чтобы можно было внедрить класс:

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

Надеюсь, что кому-то это тоже будет выгодно.

person Undeadparade    schedule 28.09.2018
comment
Хорошая попытка, но это не замена тому, что сделали Fakes. Это не повлияет на какие-либо сторонние вызовы библиотеки, работающие со временем, и требует, чтобы каждый член команды изучал и постоянно использовал заменяющий API (например, это произойдет). Я скучаю по своим подделкам, они просто работали без суеты :( - person Imre Pühvel; 17.12.2018
comment
Есть интерфейс под названием ISystemClock, который предназначен для имитации текущего datetime. - person Matthew; 05.04.2019
comment
@ ImrePühvel - если вы так сильно скучаете по фейкам, обратите внимание на пакет NuGet Pose. - person Chris Gessler; 05.05.2019
comment
@ChrisGessler, я сделал. Добро пожаловать, попробуйте, но в прошлый раз, когда я проверил, он не справился со всеми моими случаями и, похоже, еще не готов к производству. Хотя, вероятно, работает для DateTime.Now. - person Imre Pühvel; 07.05.2019
comment
Pose также не обновлялся с 6/2018, и я вообще не могу заставить его работать с .NET Core 3.1. Я получаю InvalidProgramExceptions, когда пытаюсь вызвать метод Isolate. - person metalhead; 13.12.2019