我想从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);
}
当然,如果我不包装任何东西,只是试图运行测试,我得到以下错误:
有人能解释一下我可能做错了什么吗?系统。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模拟扩展方法?
模拟单元测试的静态方法