c# - 生命周期范围由 IoC 容器处理的单元测试对象

标签 c# unit-testing dependency-injection simple-injector membus

我正在使用 Microsoft 单元测试并具有以下内容:

public class AccountCommandHandlers :
    Handler<CreateAccountCommand>,
     Handler<CloseAccountCommand>
{
    public bool CreateAccountCommandWasCalled = false;
    public bool CloseAccountCommandWasCalled = false;

    public void Handle(CreateAccountCommand command)
    {
        CreateAccountCommandWasCalled = true;
    }

    public void Handle(CloseAccountCommand command)
    {
        CloseAccountCommandWasCalled = true;
    }
}

[TestMethod]
public void CanRaiseInternalHandlers()
{
    var iocContainer = SimpleInjectorWiringForMembus.Instance;
    iocContainer.Bootstrap(
        AppDomain.CurrentDomain.GetAssemblies());

    var membus = MembusWiring.Instance;
    membus.Bootstrap();

    membus.Bus.Publish(new CreateAccountCommand() { Id = 100 });
    membus.Bus.Publish(new CloseAccountCommand() { Id = 100 });
}

我正在使用处理对象生命周期范围的 IoC 容器(简单注入(inject)器)。 Membus 将命令连接到命令处理程序,并通过 IoC 容器解析。

上面的代码运行并工作,命令处理程序将它们的局部变量设置为 true。

但是,由于 Simple Injector 处理生命周期范围,我不能向 Simple Injector 请求 AccountCommandHandler 对象,因为它会返回一个新对象,其中 CreateAccountCommandWasCalled 设置为 false。

作为单元测试的新手,除了将 CreateAccountCommandWasCalled 设置为静态变量之外,还有什么更可靠的测试方法?

最佳答案

正如其他人已经提到的,您实际上是在运行集成测试。但这不是问题。集成测试适用于测试 IoC 设置并确保应用程序的不同部分协同工作。

然而,对于集成测试,您不应该使用模拟或 stub 对象。模拟和 stub 在单元测试中有其用途。单元测试就是测试代码中尽可能小的部分。在单元测试中,您使用模拟来控制您的类具有的所有依赖项的行为。我写了一个blog一年前介绍了集成测试和单元测试之间的区别以及如何在测试中使用模拟。

在您的情况下,我不会使用带有生产配置的 IoC 容器来设置您的单元测试。相反,我会切换到在测试中手动创建对象并使用像 Moq 这样的模拟工具。控制依赖关系。

但这也是可以自动化的。一个很棒的工具是 AutoFixture . “夹具”是指运行测试所需的基线。这可能是一些示例数据、您需要的模拟和 stub 以及其他设置代码。

Mark Seemann(AutoFixture 背后的开发人员)几周前写了一篇不错的博客,内容是关于将 AutoFixture 与 IoC 一起用作 Auto-mocking Container .我建议使用类似这样的东西来构建单元测试。

关于c# - 生命周期范围由 IoC 容器处理的单元测试对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16152887/

相关文章:

c# - 关闭应用程序

ios - 如何修改依赖注入(inject)模式中的对象

dependency-injection - 城堡温莎 RemoveComponent False

java - Spring AOP 代理没有按预期工作

python - 我可以在 python 中对内部函数进行单元测试吗?

c# - 如何在统一编辑器中使用 Input.Location 和模拟位置

c# - 单击 CheckBoxList 上的特定项目时如何调用事件?

c# - 如何将对象更改保存到其 XAML?

typescript - 如何解决/抑制 IntelliJ 警告,即模拟类未在任何 Angular 模块中声明?

python - 如何使用 Tornado 单元测试来测试 "uploading a file"?