首页 > 解决方案 > 如何从 Microsoft Toolkti Mvvm 包装 Messenger 和 IMessenger 以进行单元测试

问题描述

我想从 MVVM Light 迁移到 Microsoft Toolkit MVVM,但我的单元测试有问题。我不知道如何正确包装 IMessengerExtensions 和 IMessenger 以在单元测试中使用它。

我在项目中的测试示例:

public void LoadingFinishedTest()
    {
        var messengerMock = new Mock<IMessenger>();
        messengerMock.Setup(mock => mock.Send(It.Is<IsLoadingMessage>()));

        var testedViewModelMock = new Mock<SomeViewModel>(messengerMock.Object);

        testedViewModelMock.Object.LoadingFinished();

        messengerMock.Verify(mock => mock.Send(It.Is<IsLoadingMessage>(), Times.Once);
    }

当然,如果我不包装任何东西而只是尝试运行测试,我会得到:

System.NotSupportedException : Type to mock must be an interface, a delegate, or a non-sealed, non-static class.

标签: c#unit-testingmoqword-wrap

解决方案


我也遇到了这个问题。对我来说,问题是这IMessenger.Send<TMessage>是一种扩展方法。不幸的是,据我所知,Moq 无法模拟扩展方法,因为它们是静态的

我的解决方案是创建一个IMessengerWrapper可以模拟

    // Mockable interface
    public interface IMessengerWrapper
    {
        TMessage Send<TMessage>(TMessage message)
                where TMessage : class;
    }

    // Real implementation for actual code
    public class MessengerWrapper : IMessengerWrapper
    {
        private IMessenger _messenger;

        public MessengerWrapper(IMessenger messenger)
        {
            _messenger = messenger;
        }

        public TMessage Send<TMessage>(TMessage message)
            where TMessage : class
        {
            return _messenger.Send(message);
        }
    }

然后可以IMessenger在您的单元测试中使用它,例如:

    public void LoadingFinishedTest()
    {
        var messengerMock = new Mock<IMessengerWrapper>();
        // Using It.IsAny here because It.Is requires a predicate
        messengerMock.Setup(mock => mock.Send(It.IsAny<IsLoadingMessage>()));

        var testedViewModelMock = new Mock<SomeViewModel>(messengerMock.Object);

        testedViewModelMock.Object.LoadingFinished();

        messengerMock.Verify(mock => mock.Send(It.IsAny<IsLoadingMessage>(), Times.Once);
    }

资料来源:

如何使用 Moq 模拟扩展方法?

用于单元测试的模拟静态方法


推荐阅读