无法在AutoFac中注册实例?

时间:2019-06-22 13:14:56

标签: c# unit-testing moq autofac

我想在AutoFac中使用我的项目的现有模拟实例。我不想重写我的PROD代码。因此,我发现AutoFac无法正常工作。我想我缺少什么。

我尝试了以下代码。

public AboutTideEditorMockTest () {
    aboutTideService = new AboutTideEditorService (iAboutTideEditorRepository.Object, exceptionLogServiceMock.Object);
    aboutTideServiceWithNullParam = new AboutTideEditorService (null, exceptionLogServiceMock.Object);
}

//This is my test case
[FactWithAutomaticDisplayName]
public void Test1 () {
    var cb = new ContainerBuilder ();
    var studyLoaderMock = new Mock<IAboutTideEditorService> ().Object;
    var studyLoaderMock1 = iAboutTideEditorRepository.Object;
    var studyLoaderMock2 = exceptionLogServiceMock.Object;
    cb.RegisterInstance (studyLoaderMock).As<IAboutTideEditorService> ();
    cb.RegisterInstance (studyLoaderMock1).As<IAboutTideEditorRepository> ();
    cb.RegisterInstance (studyLoaderMock2).As<IExceptionLogService> ();
    var container = cb.Build ();
    using (var scope = container.BeginLifetimeScope ()) {
        var component = scope.Resolve<AboutTideEditorService> ();
        responseData = component.AddAboutTideContent (applicationUser, aboutTide);
        Assert.Equal (ProcessStatusEnum.Invalid, responseData.Status);
    }
}

我想使用传递给“ RegisterInstance”的现有模拟实例。当我尝试调试测试用例时,我得到“ responseData”为空。我无法进入AddAboutTideContent。

1 个答案:

答案 0 :(得分:0)

您没有设置模拟返回值,需要解析IAboutTideEditorService而不是AboutTideEditorService

您还需要以不同的方式生成模拟。无需更改生产代码!

这样做:

[FactWithAutomaticDisplayName]
public void Test1() {
  var cb = new ContainerBuilder();

  var studyLoaderMock = new Mock<IAboutTideEditorService>();
  var studyLoaderMock1 = new Mock<IAboutTideEditorRepository>(); // you don't need that when resolving only IAboutTideEditorService
  var studyLoaderMock2 = new Mock<IExceptionLogService>(); // you don't need that when resolving only IAboutTideEditorService

  cb.RegisterInstance(studyLoaderMock.Object).As<IAboutTideEditorService>();
  cb.RegisterInstance(studyLoaderMock1.Object).As<IAboutTideEditorRepository>(); // you don't need that when resolving only IAboutTideEditorService
  cb.RegisterInstance(studyLoaderMock2.Object).As<IExceptionLogService>(); // you don't need that when resolving only IAboutTideEditorService

  var container = cb.Build();

  studyLoaderMock
    .Setup(x => x.AddAboutTideContent(It.IsAny<YourTypeHereForParameterA>,
                                      It.IsAny<YourTypeHereForParameterB>)
             .Returns(new MyResponseDataType()); // add the right types here necessary, I can't tell which types they are because I am not seeing the functions code

  using (var scope = container.BeginLifetimeScope()) {
    var component = scope.Resolve<IAboutTideEditorService>(); // changed to IAboutTideEditorService
    responseData = component.AddAboutTideContent(applicationUser, aboutTide);
    Assert.Equal(ProcessStatusEnum.Invalid, responseData.Status);
  }
}

您的函数调用返回null,因为这是Moq = MockBehavior.Loose的模拟的默认行为。如果要让模拟函数为非显式或显式参数返回特定值,则必须调用Setup(delegate)Returns(objectInstance)Returns(Func<ObjectType>)

通常,您的测试设置没有多大意义。您基本上只在Autofac-Container中注册了模拟,这使容器本身与您的测试无关。通常仅在直接针对实现而不是模拟进行测试时才需要使用IoC进行测试。这些测试称为Integration-Tests

这样更有意义:

[FactWithAutomaticDisplayName]
public void Test1() {
  var cb = new ContainerBuilder();

  var studyLoaderMock1 = new Mock<IAboutTideEditorRepository>();that when resolving only IAboutTideEditorService
  var studyLoaderMock2 = new Mock<IExceptionLogService>();
  var studyLoader = new AboutTideEditorService(studyLoaderMock1.Object, studyLoaderMock2.Object);

  cb.RegisterInstance(studyLoader).As<IAboutTideEditorService>();

  var container = cb.Build();

  // now setup the functions of studyLoaderMock1 and studyLoaderMock2 
  // required for your function `AddAboutTideContent` from `IAboutTideEditorService` to work.

  using (var scope = container.BeginLifetimeScope()) {
    var component = scope.Resolve<IAboutTideEditorService>(); // changed to IAboutTideEditorService
    responseData = component.AddAboutTideContent(applicationUser, aboutTide);
    Assert.Equal(ProcessStatusEnum.Invalid, responseData.Status);
  }
}

请记住,这里我假设AboutTideEditorService所需的参数顺序。有关如何使用Moq设置模拟的更多信息,请查看here