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

标签 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*
  }
}

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

最佳答案

您无法测试您的类的原因是因为您的类依赖于您的 DI 容器。这是 Service Locator anti-pattern 的实现.这是一个反模式,因为:

the problem with Service Locator is that it hides a class' dependencies, causing run-time errors instead of compile-time errors, as well as making the code more difficult to maintain because it becomes unclear when you would be introducing a breaking change.

相反,围绕

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

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

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

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.
    }
}

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

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.
    }
}

所以回答你最初的问题:

How do i unit test a class that uses IoC container classes

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

关于c# - 我如何对使用 IoC 容器类的类进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44361858/

相关文章:

c# - Autofac - 如何创建带参数的生成工厂

c# - C# 中混合数据类型的数组

c# - 如何在UWP中获取当前的ProcessID?

c# - 在 C++ 中的两个类之间共享(QList 的)实例

c# - 带有子接口(interface)的 ASP.NET MVC 4 ViewModel

c# - Visual Studio 2010 中 Web 服务的远程单元测试

unit-testing - 开发后测试的陷阱是什么?

c# - iOS 中带有 Xamarin.Forms 的 Autofac 4+ 无法构建

javascript - React Jest 匹配快照,使用子组件测试组件时崩溃

c# - 如何在 Autofac 中为 InstancePerRequest 服务编写单元测试(或回归测试)