使用 params 数组时验证模拟对象上的函数调用不匹配
我有以下测试:
[Test]
public void VerifyThat_WhenInitializingTheLoggingInterceptionFacility_TheLoggingInterceptorIsAdded()
{
var kernel = new Mock<IKernel>(MockBehavior.Loose)
{
DefaultValue = DefaultValue.Mock
};
kernel.Setup(k => k.AddFacility<LoggingInterceptionFacility>())
.Returns(kernel.Object)
.Callback(() => ((IFacility)new LoggingInterceptionFacility()).Init(kernel.Object, Mock.Of<IConfiguration>()));
kernel.Setup(k => k.Register(It.IsAny<IRegistration[]>()))
.Returns(kernel.Object)
.Verifiable();
kernel.Object.AddFacility<LoggingInterceptionFacility>();
kernel.Verify(k => k.Register(It.Is<IRegistration[]>(r => r.Contains(Component.For<LoggingInterceptor>()))));
}
如您所见,我通过调用设施的 Init(IKernel, IConfiguration)
方法来模拟内核的真实行为,该方法依次调用受保护的 Init()< /code> 方法。
受保护的 Init() 如下所示:
protected override void Init()
{
Kernel.ProxyFactory.AddInterceptorSelector(new LoggingModelInterceptorsSelector());
Kernel.Register(Component.For<LoggingInterceptor>());
}
我预计验证会通过,但事实并非如此。如果我验证是否使用 It.IsAny
调用了 Kernel.Register,则测试通过。
我在这里不匹配什么?有没有办法让这个测试通过?
I have the following test:
[Test]
public void VerifyThat_WhenInitializingTheLoggingInterceptionFacility_TheLoggingInterceptorIsAdded()
{
var kernel = new Mock<IKernel>(MockBehavior.Loose)
{
DefaultValue = DefaultValue.Mock
};
kernel.Setup(k => k.AddFacility<LoggingInterceptionFacility>())
.Returns(kernel.Object)
.Callback(() => ((IFacility)new LoggingInterceptionFacility()).Init(kernel.Object, Mock.Of<IConfiguration>()));
kernel.Setup(k => k.Register(It.IsAny<IRegistration[]>()))
.Returns(kernel.Object)
.Verifiable();
kernel.Object.AddFacility<LoggingInterceptionFacility>();
kernel.Verify(k => k.Register(It.Is<IRegistration[]>(r => r.Contains(Component.For<LoggingInterceptor>()))));
}
As you can see I am mocking the real behavior of the kernel by calling the facilitiy's Init(IKernel, IConfiguration)
method which in turns calls the protected Init()
method.
Here's how the protected Init() looks like:
protected override void Init()
{
Kernel.ProxyFactory.AddInterceptorSelector(new LoggingModelInterceptorsSelector());
Kernel.Register(Component.For<LoggingInterceptor>());
}
I expected that the verification would pass but it does not. If I verify that the Kernel.Register was called at all with It.IsAny<LoggingInterceptor>()
the test passes.
What am I not matching right here? Is there a way to make this test pass?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
看来你在这里测试太多了。通过将调用从
AddFacility
传送到LoggingInterceptionFacility.Init
,您可以有效地重新实现 Windsor 的许多内部结构。您真正需要测试的只是您的设施在内核上调用
Register
,并假设 Windsor 做了正确的事情。毕竟,它有自己的单元测试;)这样做之后,测试变得更具可读性,我认为这是最重要的方面。
编辑对
Component.For
的调用在设置和执行之间返回不同的实例。我更新了代码以反映这一点,并让验证检查组件的类型。It seems like you are testing way too much here. You are effectively reimplmenting a lot of Windsor's internals by piping calls from
AddFacility
toLoggingInterceptionFacility.Init
.All you really need to test is the fact that your facility calls
Register
on the kernel and assume that Windsor does the right thing. After all, it has unit tests of its own ;)After doing that, the test becomes much more readable, which I consider the most important aspect.
EDIT Calls to
Component.For
return different instances between setup and execution. I updated the code to reflect that and have the verification check the type of the component.