Автофикс для создания объекта со статусом c Ленивый экземпляр - PullRequest
0 голосов
/ 31 марта 2020

У меня есть класс обслуживания, который я пытаюсь протестировать, и у меня возникают некоторые трудности

Этот класс имеет закрытый конструктор, поэтому его необходимо создать из свойства c instance, возвращающего Lazy _singleton value.

public class MyService : IMyService
{
    private static readonly Lazy<IMyService> _singleton = new Lazy<IMyService>(() => new MyService(new InjectedService()));
    public static IPermissionService Instance = _singleton.Value;

    private readonly IInjectedService _injectedService;

    private MyService(IInjectedService injectedService) => _injectedService = injectedService;


    // instance method I want to test
    public void DoSomething()
    {

    }
}

Я пытаюсь использовать AutoFixture и AutoMoq для создания моего объекта, используя метод Create (), но он продолжает жаловаться, что у меня нет конструктора publi c. Если я установлю этот конструктор publi c, я все равно получу ошибку, которая, кажется, исходит от Lazy fun c.

Может кто-нибудь помочь? У меня, наверное, другие проблемы с дизайном. Я не знаю, можно ли это легко исправить.

Редактировать 1: У меня нет контейнера Io C, поэтому я могу зарегистрировать свой сервис как одиночный. Я пытался использовать этот метод для имитации внедрения службы зависимостей, чтобы я мог писать тесты с имитациями.

Я добился определенного прогресса, но я не уверен, что он мне тоже нравится ... В любом случае, я Я поделюсь тем, что у меня есть

public static class My
{
    private static readonly Lazy<IMyService> _singleton = new Lazy<IMyService>(() => new MyService(new InjectedService()));
    public static IPermissionService Service = _singleton.Value;
}

public class MyService : IMyService
{
    private readonly IInjectedService _injectedService;

    public MyService(IInjectedService injectedService) => _injectedService = injectedService;


    // instance method I want to test
    public void DoSomething()
    {

    }
}

Таким образом, я могу построить свой класс с помощью AutoFixture и заморозить макет injectedService.

И я могу использовать класс stati c таким образом

My.Service.DoSomething();

А в моих тестах

Fixture.Freeze<Mock<IInjectedService>>().Setup(...);
var service = Fixture.Create<MyService>();

service.DoSomething();
// assert my things

1 Ответ

0 голосов
/ 06 мая 2020

Это немного менее похоже на использование контейнера с автоматическим пересмешиванием, чем вам может показаться, но инъекция свойства (ублюдка) должна вас туда доставить.

В зависимости от требований к доступу пометка свойства stati c как internal может помочь или не помочь будущим читателям, но поскольку вы довольно быстро вносите изменения, позволяющие создавать класс экземпляра вне синглтона картина кажется, что вам будет хорошо с ним.

Если вы добавите свойство stati c, через которое можно внедрить зависимость, вы можете изменить свой инициализатор синглтона, чтобы использовать его значение (ублюдочное внедрение: если оно есть).

public class MyService : IService
{
  private static readonly Lazy<IService > _singleton = new Lazy<IService >(() => new 
  MyService(MyDependency ?? new BastardizedInjectable()));
  public static IService Instance = _singleton.Value;

  internal static IMyDependency MyDependency 
  { 
    get;
    set;
  }

  private readonly IMyDependency _injectedService;

  private MyService(IMyDependency injectedService) => _injectedService = injectedService;


  // instance method I want to test
  public void DoSomething()
  {
    var stuff = _injectedService.GetStuff();
  }
}

В этой реализации ваши тесты должны быть в состоянии сделать что-то вроде:

fixture.Customize<MyService>(c => c.FromFactory(() => MyService.Instance));
var depMock = fixture.Freeze<Mock<IMyDependency>>();
MyService.MyDependency = depMock;
var sut = fixture.Create<MyService>();

Инъекция ублюдка часто упоминается как анти-паттерн или, по крайней мере, идет против D в SOLID (инверсия зависимости). Если вы уверены, что на это свойство можно положиться при введении из comp- root, вам следует просто прикусить пулю и удалить ?? new BastardizedInjectable(). Будущее тебя отблагодарит.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...