gpt4 book ai didi

c# - 简单注入(inject)器,无法覆盖现有注册

转载 作者:太空狗 更新时间:2023-10-29 21:17:19 24 4
gpt4 key购买 nike

我目前是第一次使用 Simple Injector。在我的 .NET 项目中,我正在运行测试和模拟从 Web 服务返回的数据,并将对象注册到容器中,就像这样

 _container.Register<IWebServiceOrder>(() => mock.Object, Lifestyle.Transient);

这很好用。但在我的测试中,我想在第二次调用将包含更新数据的 Web 服务时测试系统的行为,因此需要更新模拟对象。

默认情况下,Simple Injector 不允许覆盖现有注册,但官方网站声明可以像下面这样更改此行为。

https://simpleinjector.readthedocs.org/en/latest/howto.html#override-existing-registrations

container.Options.AllowOverridingRegistrations = true;

不幸的是,即使使用上述代码,我第二次尝试注册对象时仍然出现错误。

The container can't be changed after the first call to GetInstance, GetAllInstances and Verify

关于为什么会发生这种情况有什么想法吗?

最佳答案

在您已经使用容器后替换现有注册几乎不会产生您期望的行为(这适用于所有 DI 库),这就是 Simple Injector 容器被锁定的原因。对此有更详细的描述 here (正如@qujck 已经指出的那样)。

首先,如果您正在编写单元测试,则根本不应该使用容器。您的单元测试应该自己创建被测类,或者您将此逻辑提取到一个方便的工厂方法中,例如:

private static MailNotifier CreateMailNotifier(
IDeposit deposit = null, ISendMail mailSender = null, ILog logger = null)
{
return new MailNotifier(
deposit ?? Substitute.For<IDeposit>(),
mailSender ?? Substitute.For<ISendMail>(),
logger ?? Substitute.For<ILog>());
}

此工厂方法是 Test Data Builder pattern 的变体.

通过使用可选参数,它允许单元测试在测试期间仅指定它需要的假实现:

public void Notify_WithValidUser_LogsAMessage()
{
// Arrange
var user = new User();

var logger = new FakeLogger();

MailNotifier sut = CreateMailNotifier(logger: logger);

// Act
sut.Notify(user);

// Assert
Assert.AreEqual(expected: 1, actual: logger.LoggedMessages.Count);
}

如果你使用容器,因为手动创建被测类太麻烦,说明你的被测类有问题(很可能违反了单一职责原则)。防止使用工具来解决设计中的问题; 您的代码在对您说话。

然而,对于集成测试,使用容器更为常见,但在这种情况下,您应该为每个集成测试简单地创建一个新容器。这样您就可以毫无问题地添加或替换 IWebServiceOrder

关于c# - 简单注入(inject)器,无法覆盖现有注册,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26484696/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com