Unit testing 如何重置autofac容器?

Unit testing 如何重置autofac容器?,unit-testing,autofac,Unit Testing,Autofac,在我的测试中,我设置了一个autofac容器,它返回一些真实的实现和一些模拟(DB,外部系统) 问题在于,每次测试后,我都会处理容器并创建一个新容器: Autofac.IContainer.Dispose()和Container=builder.Build() 已经注册的实例仍然存在 如何重置容器,使其再次“像新的一样” 我想这样做的原因是——我想用另一个模拟实例替换一个模拟实例。它被注册为单身汉 ----编辑 谢谢你的回答。我决定添加更多的代码,并描述我实际要实现的目标。但这实际上是另一个话题

在我的测试中,我设置了一个autofac容器,它返回一些真实的实现和一些模拟(DB,外部系统)

问题在于,每次测试后,我都会处理容器并创建一个新容器:
Autofac.IContainer.Dispose()
Container=builder.Build()
已经注册的实例仍然存在

如何重置容器,使其再次“像新的一样”

我想这样做的原因是——我想用另一个模拟实例替换一个模拟实例。它被注册为单身汉

----编辑

谢谢你的回答。我决定添加更多的代码,并描述我实际要实现的目标。但这实际上是另一个话题(prabably已经回答了问题-单元测试CQR)

我的应用程序包含静态IContainer属性:

public static IContainer Container { get; private set; }
每次执行测试后,我通过调用这两个方法再次创建它:

public static ContainerBuilder Compose(IEnumerable<DependencyProvider> dependencyProviders)
{
    var collection = dependencyProviders as List<DependencyProvider> ?? dependencyProviders.ToList();
    var included = new HashSet<DependencyProvider>(collection);
    var includedTypes = new HashSet<Type>(collection.Select(x => x.GetType()));
    var currentWorkingSet = new List<DependencyProvider>(collection);

    while (true)
    {
        var candidates = currentWorkingSet.SelectMany(x => x.GetDependencies());
        var typesToBeAdded = candidates.Where(x => !includedTypes.Contains(x)).Distinct().ToList();
        if (typesToBeAdded.Any() == false)
            break;

       currentWorkingSet.Clear();
       foreach (var type in typesToBeAdded)
       {
            includedTypes.Add(type);
            var instance = CreateInstance(type);
            included.Add(instance);
            currentWorkingSet.Add(instance);
       }
    }

return BuildContainer(included);
}
TestDependencyProvider
是为每个测试创建的,包含moqed实例。它注册这些模拟并
x.GetDependencies()
使用原始容器注册,即
container.RegisterAssemblyTypes(Assembly.getExecutionGassembly()).AsClosedTypesOf(typeof(iaggegateBusinessRuleForEvent))

我最感兴趣的类型是
IAggregateBusinessRuleForEvent)
的一种实现

结果是:

Hello
A
Hello
A

默认情况下,Autofac会用后续注册覆盖以前的注册。这意味着您无需执行任何特殊操作,只需使用新实例更新容器:

var builder = new ContainerBuilder();
builder.RegisterInstance(new Sample("A")).SingleInstance();
var container = builder.Build();
var sample = container.Resolve<Sample>();
// do your test

...

// new test using same container
var updater = new ContainerBuilder();
updater.RegisterInstance(new Sample("B")).SingleInstance();
updater.Update(container); // overwrites existing registrations
var sample = container.Resolve<Sample>(); // returns "B"
var builder=newcontainerbuilder();
RegisterInstance(新示例(“A”)).SingleInstance();
var container=builder.Build();
var sample=container.Resolve();
//做你的测试
...
//使用相同容器的新测试
var updater=newcontainerbuilder();
updater.RegisterInstance(新示例(“B”)).SingleInstance();
updater.Update(容器);//覆盖现有注册
var sample=container.Resolve();//返回“B”

为什么在测试中使用DI容器而不是模拟框架(例如:Moq)?我不是100%确定我做得对,但这里的scnario是一个CQRS,事件源MVC应用程序。我的测试场景是执行一个命令并断言weather是否正确执行-调用了Moq对象。命令由处理程序处理,处理程序在IoC中注册,它的依赖关系由构造函数注入。这里的问题是,即使在Dispose之后,处理程序也不会再次创建,但仍然存在于容器中。在单元测试中使用DI容器可能有一些正当的理由,但这不是“正确”的方法。是的。你完全正确。这些是真正的集成测试,使用CQRS框架在许多类中执行代码。我可以很容易地对我的
RulaA
类进行单元测试,但我看不出有什么意义:/这些类中的所有方法都有一个或两个语句-对它们进行单元测试有什么意义吗?我编写了一个示例,但它不起作用:/我已将测试和结果添加到问题中。@Karpik:它起作用了--在
//新测试中…
您需要调用
的部分代码中。在
更新程序上注册
方法,而不是在
生成器上注册
方法,与我在示例中所做的完全相同。
public interface IExample<T>
{
    void Hello();
}

public interface IExampleDependecy
{
    void SaySomething();
}

public class Example : IExample<string>
{
    private IExampleDependecy _dependecy;

    public Example(IExampleDependecy dependecy)
    {
        _dependecy = dependecy;
    }

    public void Hello()
    {
        Console.WriteLine("Hello");
        _dependecy.SaySomething();
    }
}

[TestMethod]
public void T()
{
    // first test
    var builder = new ContainerBuilder();
    builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()).AsClosedTypesOf(typeof(IExample<>));
    var mockA = new Moq.Mock<IExampleDependecy>();
    mockA.Setup(d => d.SaySomething()).Callback(() => Console.WriteLine("A"));

    builder.RegisterInstance(mockA.Object).SingleInstance();
    var container = builder.Build();

    var sample1 = container.Resolve<IExample<string>>();
    sample1.Hello();



    // new test using same container
    var updater = new ContainerBuilder();
    builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()).AsClosedTypesOf(typeof(IExample<>));
    var mockB = new Moq.Mock<IExampleDependecy>();
    mockB.Setup(d => d.SaySomething()).Callback(() => Console.WriteLine("B"));
    builder.RegisterInstance(mockB.Object).SingleInstance();
    updater.Update(container); // overwrites existing registrations

    var sample2 = container.Resolve<IExample<string>>();
    sample2.Hello();
}
Hello
A
Hello
A
var builder = new ContainerBuilder();
builder.RegisterInstance(new Sample("A")).SingleInstance();
var container = builder.Build();
var sample = container.Resolve<Sample>();
// do your test

...

// new test using same container
var updater = new ContainerBuilder();
updater.RegisterInstance(new Sample("B")).SingleInstance();
updater.Update(container); // overwrites existing registrations
var sample = container.Resolve<Sample>(); // returns "B"