对依赖项注入进行单元测试

Unit testing the dependency injection(对依赖项注入进行单元测试)
本文介绍了对依赖项注入进行单元测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为IOC使用Autofac

这是我的容器启动器类,负责注册依赖项。

 public class ContainerInit
 {
      public static IContainer BuildContainer()
      {
            var conFac = new ContainerFactory();
            var builder = new ContainerBuilder();
            builder.Register(conFac).As<IContainerFactory>().SingleInstance();
            builder.Register(c=> new MainClass(conFac)).As<IMainClass>().SingleInstance();
            builder.Register(c=> new Database(conFac)).As<IDatabase>().SingleInstance();
             var logger = LoggUtil.CreateLogger();
            builder.Register(logger).As<ILogger>().SingleInstance();

            var container = builder.Build();
            ContainerFactory.SetContainer(container);
            return container;
      }
 }

这种方法的问题是,我需要将IContainerFactory传递给我在应用程序中使用的每个类的构造函数,如下所示

  public class MainClass: IMainClass
  {       
      private readonly ILogger _logger;
      private readonly IDatabase _db;
      public MainClass(IContainerFactory containerFactory)
      {
              _logger = containerFactory.GetInstance<ILogger>();  
              _db =  containerFactory.GetInstance<IDatabase>(); //example       
      }
      public AddDetails(Data data)
      {
        //do some business operations 
        _db.Add(data);
        _logger.Information("added");
      }
  }

所以很难对这些类进行单元测试。

怎样才能想出一个好的解决方案?

推荐答案

您当前的服务定位器反模式使您的代码难以单独测试,并使类在其实际依赖项方面具有误导性。

MainClass应重构为Explicit Dependencies Principle

public class MainClass : IMainClass  
    private readonly ILogger logger;
    private readonly IDatabase db;

    public MainClass(ILogger logger, IDatabase db) {
        this.logger = logger;  
        this.db = db;
    }

    public void AddDetails(Data data) {
        //do some business operations 
        db.Add(data);
        logger.Information("added");
    }
}

您的任何其他依赖于容器工厂的类也应遵循相同的模式,如Database

不过,您还需要相应地重构容器注册

public class ContainerInit {
    public static IContainer BuildContainer() {
        var builder = new ContainerBuilder();
        builder.RegisterType<MainClass>().As<IMainClass>().SingleInstance();
        builder.RegisterType<Database>().As<IDatabase>().SingleInstance();
        var logger = LoggUtil.CreateLogger();
        builder.Register(logger).As<ILogger>().SingleInstance();

        var container = builder.Build();
        return container;
    }
}

测试MainClass需要您仅模拟被测试类的必要依赖项。

[TestClass]
public class MainClassTests {    
    [TestMethod]
    public void Should_AddDetails_To_Database() {
        // Arrange
        var mockDb = new Mock<IDatabase>();
        var data = new Data();
        var mainClass = new MainClass(Mock.Of<ILogger>(), mockDb.Object);

        // Act
        mainClass.AddDetails(data);

        // Assert    
        mockDb.Verify(_ => _.Add(data), Times.Once);
    }
}

这篇关于对依赖项注入进行单元测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

DispatcherQueue null when trying to update Ui property in ViewModel(尝试更新ViewModel中的Ui属性时DispatcherQueue为空)
Drawing over all windows on multiple monitors(在多个监视器上绘制所有窗口)
Programmatically show the desktop(以编程方式显示桌面)
c# Generic Setlt;Tgt; implementation to access objects by type(按类型访问对象的C#泛型集实现)
InvalidOperationException When using Context Injection in ASP.Net Core(在ASP.NET核心中使用上下文注入时发生InvalidOperationException)
LINQ many-to-many relationship, how to write a correct WHERE clause?(LINQ多对多关系,如何写一个正确的WHERE子句?)