如何从Microsoft的 CommunityToolkit.Mvvm 包中包装 Messenger 和 IMessenger 以进行单元测试



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

我在我的项目中的一个测试示例:

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);
}

当然,如果我不包装任何东西,只是试图运行测试,我得到以下错误:

系统。NotSupportedException:要模拟的类型必须是接口、委托或非密封、非静态类。

有人能解释一下我可能做错了什么吗?

假设SomeViewModel是被测试的对象,应该使用它的实际实例来执行测试用例

public void LoadingFinishedTest() {
// Arrange
var messengerMock = new Mock<IMessenger>();
messengerMock.Setup(mock => mock.Send(It.Is<IsLoadingMessage>()));
var subject = new SomeViewModel(messengerMock.Object);
// Act
subject.Object.LoadingFinished();
// Assert
messengerMock.Verify(mock => mock.Send(It.Is<IsLoadingMessage>(), Times.Once);
}

验证也可以在安装过程中配置

例如

public void LoadingFinishedTest() {
// Arrange
var messengerMock = new Mock<IMessenger>();
messengerMock
.Setup(mock => mock.Send(It.Is<IsLoadingMessage>()))
.Verifiable(); //<-- NOTE THIS
var subject = new SomeViewModel(messengerMock.Object);
// Act
subject.Object.LoadingFinished();
// Assert
messengerMock.Verify(); //<-- verifying expected behavior that was setup
}

我也遇到了这个问题。对我来说,问题是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模拟扩展方法?

模拟单元测试的静态方法

相关内容

  • 没有找到相关文章

最新更新