【问题标题】:Invalid verify on a non-virtual on an interface对接口上的非虚拟设备进行无效验证
【发布时间】:2017-03-25 20:41:11
【问题描述】:

以下代码引发异常,MOQ 抱怨:

“在非虚拟机上验证无效”

但我在模拟一个界面。我一定做过好几次这样的测试,但这次我无法弄清楚问题出在哪里。

[TestFixture]
public class RegisterDeviceCommandHandlerTests
{
    private RegisterDeviceCommandHandler _handler;
    private readonly Mock<IClientRepository> _clientRepositoryMock = new Mock<IClientRepository>();
    private readonly Mock<IMessageHandlerContext>  _busMock = new Mock<IMessageHandlerContext>();
    private readonly Mock<IClientEncryptionProvider> _clientEncryptionProviderMock = new Mock<IClientEncryptionProvider>();


    [Test]
    public async Task GivenAnUnregisteredDeviceWhenTheDeviceIsAddedThenADeviceRegistrationCompletedEventShouldBePublished()
    {
        _clientRepositoryMock.Setup(x => x.RegisterClient(It.IsAny<byte[]>(), It.IsAny<string>(),
                It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
            .Returns(RegistrationClientOperationResult.Registered);

        var clientIdentity = new ClientIdentity
        {
            HostName = "HostName",
            MacAddress = "MacAddress",
            MachineId = "MachineId"
        };

        _clientEncryptionProviderMock.Setup(x => x.DecryptIdentity(It.IsAny<byte[]>())).Returns(clientIdentity);

        _handler = new RegisterDeviceCommandHandler(_clientEncryptionProviderMock.Object, _clientRepositoryMock.Object)
        {
            Bus = _busMock.Object
        };

        await _handler.HandleAsync(new RegisterDeviceCommand
        {
            Identity = new byte[] { 1, 2 }
        });

        _busMock.Verify(x => x.Publish(It.IsAny<DeviceRegistrationCompletedEvent>()));
    }
}

【问题讨论】:

  • 我在想Publish是不是一个扩展方法而不是接口上的方法?
  • @Nkosi 你是对的,我刚刚找到它。这让我的事情变得更复杂了。
  • 如果您知道扩展方法实际调用的成员是什么,您可以验证这一点,但如果您不知道扩展的内部工作原理,这将是一个很好的猜测。

标签: c# unit-testing moq nservicebus


【解决方案1】:

找到了。 IMessageHandlerContext 继承自 IPipelineContext,它有一个 Publish 方法

/// <summary>
/// Publish the message to subscribers.
/// </summary>
/// <param name="message">The message to publish.</param>
/// <param name="options">The options for the publish.</param>
Task Publish(object message, PublishOptions options);

接受一个参数的extension method 可用于接口和该方法。

/// <summary>
/// Publish the message to subscribers.
/// </summary>
/// <param name="context">The instance of <see cref="IPipelineContext" /> to use for the action.</param>
/// <param name="message">The message to publish.</param>
public static Task Publish(this IPipelineContext context, object message)
{
    Guard.AgainstNull(nameof(context), context);
    Guard.AgainstNull(nameof(message), message);

    return context.Publish(message, new PublishOptions());
}

因此,要使用模拟满足扩展方法,您需要验证

_busMock.Verify(_ => _.Publish(It.IsAny<DeviceRegistrationCompletedEvent>(), Is.IsAny<PublishOptions>()));

【讨论】:

  • @Marco,找到了相关接口的源代码并提出了解决方法。
  • 我最终使用了他们自己的测试库。无论如何谢谢:)
猜你喜欢
  • 2014-07-19
  • 1970-01-01
  • 1970-01-01
  • 2014-01-29
  • 1970-01-01
  • 2011-09-22
  • 2022-01-11
  • 2015-08-16
  • 1970-01-01
相关资源
最近更新 更多