Autofixture: Получить экземпляр внутреннего интерфейса, созданного AutoMoqData.

Созданный на 26 апр. 2018  ·  8Комментарии  ·  Источник: AutoFixture/AutoFixture

Привет,

Я пытаюсь получить экземпляр внутреннего Mocked Interface, созданного AutoMoqData, для настройки интерфейса.

Есть ли способ сделать что-то подобное

[Theory, AutoMoqData]
public void Dummy(IFixture fixture, ComplexClassWithInnerInterface sut)
{
    fixture.GetInstance<IInnerInterfaceMockCreatedByAutoMoqData>().Setup(x => x.Method).Result(something);

    Assert.Equal(String.Empty, String.Empty);
}

Спасибо

question

Самый полезный комментарий

Спасибо @xlecoustillier за отличный ответ. В принципе, я бы посоветовал сделать то же самое, поскольку я постоянно следую этому шаблону в своих тестах.

Но для 30 интерфейсов довольно некрасиво иметь их в параметрах метода.

Что ж, этот аргумент выглядит немного странным. Вероятно, что-то не так с дизайном протестированного кода, если вам нужно настроить 30 зависимостей для создания сценария 😟 Я на 99% @ploeh посоветует вам сначала просмотреть код, прежде чем продолжить, согласно его совету, рекомендуется иметь максимум 3-4 зависимости 😅

Таким образом, кажется невозможным получить автоматически созданные макеты из контейнера приспособления. Они не внедряются по умолчанию, поэтому, если прибор имеет метод, подобный GetInstance, он не будет ничего возвращать для автоматически созданных макетов.

Я не уверен на 100%, что правильно понял все сообщение, но, судя по тому, что я понял, вы правы. По умолчанию все сгенерированные объекты являются временными, и fixture их не сохраняет. Если вы хотите сделать конкретный объект синглтоном, вы должны использовать fixture.Freeze<>() API или атрибут [Frozen] или любой другой подходящий API.
Существующее поведение по умолчанию было разработано для охвата распространенных сценариев, и в большинстве случаев вы _не хотите_ иметь один и тот же объект для каждого типа.

Если вы все еще ищете помощь с нашей стороны, укажите более точное требование, которое у вас есть. Лучше поделитесь достаточным количеством кода, чтобы продемонстрировать текущие ограничения и цель, которую вы хотите достичь - это поможет лучше синхронизировать 😉

Спасибо.

Все 8 Комментарий

пытаться

Mock.Get(sut).Setup(x => x.Method).Result(something);

Вы увидите, что экземпляр объекта не был создан Moq. доступ к сут.

Это действительно будет работать, если интерфейс находится в общедоступном свойстве.
Mock.Get (sut.InnerInterface) .Setup (x => x.Method) .Result (something);

Но что, если интерфейс имитируется, а конструктор внедрен, зарегистрирован в контейнере IoC, но недоступен в sut с общедоступным свойством?

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

[Theory, AutoMoqData]
public void Dummy(
    IFixture fixture, 
    [Frozen]Mock<YourInnerInterface> innerInterfaceMock,
    ComplexClassWithInnerInterface sut)
{
    innerInterfaceMock.Setup(x => x.Method).Result(something);
    sut.DoSomething();
    Assert.Equal(String.Empty, String.Empty);
}

Будьте осторожны, всегда создавайте замороженные макеты перед швом, чтобы они уже существовали на момент создания шва и, следовательно, вводились правильно.

См. Для справки блог ploeh .

Привет,
Я уже этим занимался. Но для 30 интерфейсов довольно некрасиво иметь их в параметрах метода.
Ваш код напомнил мне, что AutoMoqData не замораживает все имитируемые интерфейсы. Таким образом, кажется невозможным получить автоматически созданные макеты из контейнера приспособления. Они не внедряются по умолчанию, поэтому, если прибор имеет метод, подобный GetInstance, он не будет ничего возвращать для автоматически созданных макетов. Вот почему я получаю дубликаты, если замораживаю макет с экземпляром фикстуры. Единственный способ, которым я вижу, это сработает, - это если бы sut мог быть обновлен с помощью более поздних замороженных mock'ов, но это было бы некрасиво. Самый простой способ - использовать AutoMoqData для создания IFixture, заморозить и настроить макеты в методе тестирования, а затем создать sut. С помощью этой настройки я могу создать многоразовый вспомогательный метод для замораживания и настройки моков.

Спасибо

Спасибо @xlecoustillier за отличный ответ. В принципе, я бы посоветовал сделать то же самое, поскольку я постоянно следую этому шаблону в своих тестах.

Но для 30 интерфейсов довольно некрасиво иметь их в параметрах метода.

Что ж, этот аргумент выглядит немного странным. Вероятно, что-то не так с дизайном протестированного кода, если вам нужно настроить 30 зависимостей для создания сценария 😟 Я на 99% @ploeh посоветует вам сначала просмотреть код, прежде чем продолжить, согласно его совету, рекомендуется иметь максимум 3-4 зависимости 😅

Таким образом, кажется невозможным получить автоматически созданные макеты из контейнера приспособления. Они не внедряются по умолчанию, поэтому, если прибор имеет метод, подобный GetInstance, он не будет ничего возвращать для автоматически созданных макетов.

Я не уверен на 100%, что правильно понял все сообщение, но, судя по тому, что я понял, вы правы. По умолчанию все сгенерированные объекты являются временными, и fixture их не сохраняет. Если вы хотите сделать конкретный объект синглтоном, вы должны использовать fixture.Freeze<>() API или атрибут [Frozen] или любой другой подходящий API.
Существующее поведение по умолчанию было разработано для охвата распространенных сценариев, и в большинстве случаев вы _не хотите_ иметь один и тот же объект для каждого типа.

Если вы все еще ищете помощь с нашей стороны, укажите более точное требование, которое у вас есть. Лучше поделитесь достаточным количеством кода, чтобы продемонстрировать текущие ограничения и цель, которую вы хотите достичь - это поможет лучше синхронизировать 😉

Спасибо.

Да, я бы предположил, что 30 зависимостей - это слишком много.

Что касается внедрения зависимостей, использование атрибута [Frozen] , как предлагает @xlecoustillier , является одним из вариантов и фактически является причиной того, что этот атрибут изначально существует.

Я часто использую Mock.Get(sut.Dep1) .

Но что, если интерфейс [...] внедрен конструктором [...], но недоступен в sut с общедоступным свойством?

Почему бы тогда не выставить его на обозрение как собственность? То, что сочиняете, тоже можно выставить. . Инкапсуляция не нарушается.

Я чувствую, что хочу добавить @ploeh , указав, что лучший подход - раскрыть зависимости как свойства класса без обогащения вашей абстракции, что было бы не чем иным, как утечкой вашей реализации!

@ malylemire1 Закрытие, поскольку кажется, что дополнительная помощь не требуется. Пожалуйста, дайте нам знать, если мы еще чем-то можем вам помочь 😉

Спасибо, что еще раз подняли вопрос! 👍

Была ли эта страница полезной?
0 / 5 - 0 рейтинги