我如何对使用IoC容器类的类进行单元测试

vin*_*vin 2 c# unit-testing autofac

我在我的项目中使用Autofac,但我无法对一个特定的类进行单元测试.

请考虑以下场景:

//Class to be tested
public Class A
{
  private SomeAutoFacClass B;

  public void DoSomething()
  {
    B = scope.Resolve<ClassName>();// Resolve the object needed 
    // Do something with instance B
  }
}

// Test class
public Class ATest
{
  private A a;

  [test]
  public void TestMethod()
  {
    a.DoSomething();//*This method causes a null reference exception as it tries to resolve the objects*
  }
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,由于依赖注入,我无法对单元测试用例进行单元测试.我该如何解决这个问题?我还尝试使用Moq创建一个autofaccontainer.但那也失败了.

Ste*_*ven 6

您无法测试课程的原因是因为您的课程依赖于您的DI容器.这是Service Locator反模式的实现.这是一种反模式,因为:

与服务定位的问题是,它隐藏了一个类的依赖性,从而导致运行时错误而不是编译时错误,以及使代码更难以维护,因为它变得不明确时,你会被引入重大更改.

相反,设计你的课程

  • 构造函数注入,以防该类是一个组件(包含应用程序行为的类),您可以通过构造函数注入类直接需要的依赖项
  • 方法当类是像实体这样的以数据为中心的对象时注入,这意味着依赖关系被提供给此类的公共方法,其中消费类仅使用该依赖关系,但不存储它.

组件由DI容器构建并在组合根中注册,而以数据为中心的对象new在组合根之外的代码中编辑.在这种情况下,您需要将依赖项传递给已构造的对象.

如果您构建并测试组件,您的代码通常如下所示:

public class ComponentA
{
    private ClassName b;

    public ComponentA(ClassName b)
    {
        this.b = b;
    }

    public void DoSomething()
    {
        // Do something with instance B
    }
}

// Test class
public Class ATest
{
    [test]
    public void TestMethod()
    {
        // Arrange
        B b = new FakeB();

        var a = new ComponentA(b);

        // Act
        a.DoSomething();

        // Assert
        // Check whether be was invoked correctly.
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您构建并测试需要依赖其某个操作的以数据为中心的对象,则您的代码通常如下所示:

public class EntityA
{
    public string Name { get; set; }
    public int Age { get; set; }

    public void DoSomething(ClassName b)
    {
        // Do something with instance B
    }
}

// Test class
public Class ATest
{
    [test]
    public void TestMethod()
    {
        // Arrange
        B b = new FakeB();

        var a = new EntityA { Name = "Bert", Age = 56 };

        // Act
        a.DoSomething(b);

        // Assert
        // Check whether be was invoked correctly.
    }
}
Run Code Online (Sandbox Code Playgroud)

那么回答你的初步问题:

我如何对使用IoC容器类的类进行单元测试

你没有.您的应用程序代码不应该依赖于DI容器,因为这会导致各种复杂情况,例如难以测试.