使用 params 数组时验证模拟对象上的函数调用不匹配

发布于 2024-11-07 07:32:03 字数 1413 浏览 0 评论 0原文

我有以下测试:

[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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

雪花飘飘的天空 2024-11-14 07:32:03

看来你在这里测试太多了。通过将调用从 AddFacility 传送到 LoggingInterceptionFacility.Init,您可以有效地重新实现 Windsor 的许多内部结构。

真正需要测试的只是您的设施在内核上调用Register,并假设 Windsor 做了正确的事情。毕竟,它有自己的单元测试;)

这样做之后,测试变得更具可读性,我认为这是最重要的方面。

[Test]
public void VerifyThat_WhenInitializingTheLoggingInterceptionFacility_TheLoggingInterceptorIsAdded()
{
    var kernel = new Mock<IKernel>();

    kernel.Setup(k => k.Register(It.IsAny<IRegistration[]>()))
                  .Returns(kernel.Object)
                  .Verifiable();
    //Explicit interface implementation requires casting to the interface
    ((IFacility)new LoggingInterceptionFacility()).Init(kernel.Object, Mock.Of<IConfiguration>().Object);
    //verify the type of registration here
    kernel.Verify(k => k.Register(It.Is<IRegistration[]>(r => r[0] is ComponentRegistration<LoggingInterceptor>);
}

编辑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 to LoggingInterceptionFacility.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.

[Test]
public void VerifyThat_WhenInitializingTheLoggingInterceptionFacility_TheLoggingInterceptorIsAdded()
{
    var kernel = new Mock<IKernel>();

    kernel.Setup(k => k.Register(It.IsAny<IRegistration[]>()))
                  .Returns(kernel.Object)
                  .Verifiable();
    //Explicit interface implementation requires casting to the interface
    ((IFacility)new LoggingInterceptionFacility()).Init(kernel.Object, Mock.Of<IConfiguration>().Object);
    //verify the type of registration here
    kernel.Verify(k => k.Register(It.Is<IRegistration[]>(r => r[0] is ComponentRegistration<LoggingInterceptor>);
}

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文