Использование autofac с moq

#c# #moq #autofac

#c# #moq #autofac

Вопрос:

Мне нужно зарегистрировать мой контейнер Autofac с определенным интерфейсом, для этого случая я хочу разрешить макет.

Как я могу это сделать?

Я пытался:

 var AppContainer = ApplicationContainer.GetApplicationContainer();  
var cb = new ContainerBuilder();
cb.RegisterType<Mock<IStudyLoader>>().As<IStudyLoader>().SingleInstance();
cb.Update(AppContainer);
  

Я не хочу изменять свой код, чтобы разрешить что-то другое, чем IStudyLoader , но Mock<IStudyLoader> не может быть заменено на IStudyLoader ; например, Mock<IStudyLoader>.Object может быть заменено на IStudyLoader , но я не могу зарегистрироваться Mock<IStudyLoader>.Object , потому что это не тип.

Поправьте меня, пожалуйста; у меня такое чувство, что я чего-то не понимаю.

(У меня есть другое ограничение, я не могу использовать другой контейнер, кроме ApplicationContainer.GetApplicationContainer() )

(Я думаю, что лучше вручную вводить зависимость при тестировании, но на этот раз я не хочу менять производственный код.)

Ответ №1:

Я нашел решение, да, это возможно!

   var AppContainer = ApplicationContainer.GetApplicationContainer();
  var studyLoaderMock = new Mock<IStudyLoader>().Object;
  cb.RegisterInstance(studyLoaderMock).As<IStudyLoader>();
  cb.Update(AppContainer);
  

Ответ №2:

Старый вопрос, но AutoFac теперь, начиная с версии 4.0.1, поддерживает Moq4 и предоставляет дополнительный пакет, который вы можете установить Autofac.Extras.Moq

     Install-Package Autofac.Extras.Moq
  

Autofac.Дополнительно.Moq автоматически устанавливает как AutoFac, так и Moq

Вам не нужно создавать контейнер и регистрировать StudyLoader. Это неявно определено Autofac.Extras.Moq.

Autofac.Дополнительно.Moq ценен для вложенной зависимости. Вам не нужно регистрировать весь график зависимостей. Только макет вашего объекта SystemUnderTest SUT

Вы можете реализовать свой тестовый пример, как указано ниже:

          [TestFixture]
        class StudyLoaderTest
        {
            [Test]
            public void Test()
            {
                using (var mock = AutoMock.GetLoose())
                {
                    // The AutoMock class will inject a mock IStudyLoader
                    // into the StudyLoader constructor
                    //no need to create/configure a container
                    var studyLoader = mock.Create<StudyLoader>();               
                    Assert.AreEqual("hi AutoFac Moq", studyLoader.Name);
                }
            }
        }

         class StudyLoader : IStudyLoader
        {
            public string Name { get; set; } = "hi AutoFac Moq";
        }
         interface IStudyLoader
        {
            string Name { get; set; }
        }
  

Ответ №3:

Вызывается метод, который вы ищете RegisterInstance :

 var mock = ...;
var cb = new ContainerBuilder();
cb.RegisterInstance(mock.Object);
var container = cb.Build();
  

Тем не менее, существующий контейнер (в вашем случае AppContainer), у которого уже есть регистрация для интерфейса, который вы хотите создать, не сможет разрешить экземпляр. Он продолжит разрешать производственный экземпляр.

«Обходной путь», которому я бы настоятельно посоветовал вам следовать, заключается в том, чтобы не включать AppContainer в ваш тест, а скорее создать контейнер, адаптированный для вашего теста, чтобы вы могли лучше контролировать, что туда входит, а что нет. В результате вы получаете возможность зарегистрировать любой макет экземпляра, который вам нужен, вместе с SUT.

Ответ №4:

У меня нет особого опыта работы с autofac, но большинство других контейнеров, с которыми я работал, позволяют регистрировать экземпляр object, который уже создан. Таким образом, вы можете создать свой макет, а затем зарегистрировать макет.Объект как реализация для IStudyLoader. Обратитесь к документации autofac о том, как это сделать.

Ответ №5:

Поскольку этот вопрос был задан, теперь существует AutoFac.Extras.Moq пакет, поддерживаемый AutoFac:

http://autofaccn.readthedocs.io/en/latest/integration/moq.html

Это позволяет вам создавать зависимости на лету в ваших модульных тестах.