C# 覆盖Autofac注册-与DI集成测试

C# 覆盖Autofac注册-与DI集成测试,c#,unit-testing,dependency-injection,integration-testing,autofac,C#,Unit Testing,Dependency Injection,Integration Testing,Autofac,我为我的应用程序编写集成测试,并为此使用容器。我希望能够像在实际运行中一样注册所有组件,然后覆盖一些组件并将它们切换到使用存根实现 我不想仅仅因为我想测试真实的东西就将DI分离并拥有一个用于测试的容器 这样做似乎也很丑陋: public class MyRegistrations { public static RegisterAll(bool isInTest= false) { if (isTest) {

我为我的应用程序编写集成测试,并为此使用容器。我希望能够像在实际运行中一样注册所有组件,然后覆盖一些组件并将它们切换到使用存根实现

我不想仅仅因为我想测试真实的东西就将DI分离并拥有一个用于测试的容器

这样做似乎也很丑陋:

public class MyRegistrations
{
     public static RegisterAll(bool isInTest= false)
     {
           if (isTest) 
           {
             // Register test fakes
            }
            else
                  // Register real components
      }
}
所以我想在我的测试环境中覆盖注册。应该怎么做

还有其他更好的方法来实现我的目标吗


谢谢,例如,您可以在composition根目录中创建一个静态操作方法来更改当前配置,并在测试期间调用它。例如:

public class CompositionRoot
{
    public static Action<IContainer> OverrideContainer = c => { };

    internal static IContainer CreateContainer()
    {
        ContainerBuilder builder = new ContainerBuilder();

        /// etc. etc.

        var container = builder.Build();

        OverrideContainer(container);

        return container;
    }
}
希望有帮助:)

Autofac将使用最后注册的组件作为默认提供程序 那项服务的价值

在排列/设置/测试阶段,注册模拟,然后解决SUT:

[SetUp]
public void TestInit()
{
    Mock<IFoo> mock = new Mock<IFoo>();
    builder.RegisterInstance(mock.object).As<IFoo>();
    ...
    ...
    _target = builder.Resolve<The component>();
}
[设置]
公共无效测试()
{
Mock Mock=新Mock();
RegisterInstance(mock.object).As();
...
...
_target=builder.Resolve();
}
注:


单例、静态成员和单例生活方式(注册)可能会引起一些问题。…

如果您想将集成测试从API写入数据库,可以使用XUnit。XUnit使用TestHost和WebApplicationFactory创建被测系统。使用XUnit,通过将测试服务添加到服务集合来模拟测试服务非常容易


我用XUnit做了一个开源项目,用mySQL数据库测试我的API工作。例如,请访问此处

我可以问一下为什么要模拟组件作为集成测试的一部分吗?您不是在寻找您的应用程序的端到端功能,而这些功能是假的组件无法实现的吗?即使这意味着写入实际的数据库实例或WCF端点等@StephenRoss,在某些情况下,在集成测试中很难模拟特定情况,但您希望将其作为集成测试的一部分进行测试;例如,C&C代理,当磁盘已满C&C服务器时发出警报。@OldFox如果这是对我的应用程序执行的集成测试,我仍然希望将磁盘加载到最大值。您(应该)已经在单元测试中测试交互是否正确处理,但是您现在正在检查以确保所有内容都正确地端到端工作(正确集成)。如果这意味着将10Gb的空白数据写入磁盘进行测试,那么就这样吧,否则我们怎么知道我们在正确的时间正确地处理了(我期望)事件等@StephenRoss给出了磁盘已满的示例,展示了依赖关系过多的场景。。。光盘已满时,生成服务器/测试运行程序可能无法按预期运行。是的,你也应该用UT覆盖它。。。根据定义,集成测试是将多个模块组合在一起,并将它们作为一个组进行测试,因此将它们与它们的某些依赖项隔离并没有什么错。我建议您阅读更多关于@OldFox的内容,我并不反对您对集成测试的期望。我觉得这样做的问题是,在集成中进行模拟会使您无法在其正常运行时环境中充分使用功能(而不管是子系统集成还是整个系统)。你的回答涵盖了OP想要的,我只是想知道他们为什么要这么做。谢谢,这会让生活变得轻松,但是你说单身会有问题是什么意思?几乎我的应用程序的所有组件都是singletons@S.Peter我读了你在问题中的评论,你可能不会面对我所说的问题;您的一些单例可能包含一些对对象的引用,您可以在场景X中模拟它们,但在场景Y中不模拟它们。这些问题通常存在于web服务中。。。
[SetUp]
public void TestInit()
{
    Mock<IFoo> mock = new Mock<IFoo>();
    builder.RegisterInstance(mock.object).As<IFoo>();
    ...
    ...
    _target = builder.Resolve<The component>();
}