Is this an acceptable way to test MVVM-Light Toolkit Messages?
[TestMethod()]
public void ShowSetup_SendsMessage_WhenShowSetupCommandCalled()
{
//Arrange
Messenger.Reset();
MainViewModel target = new MainViewModel();
bool wasCalled = false;
Messenger.Default.Register<NotificationMessage>(this,"Settings",(msg) => wasCalled = true);
//Act
target.ShowSetupCommand.Execute(null);
//Assert
Assert.IsTrue(wasCalled);
}
I see there is an IMessenger inte开发者_运维百科rface and I tried to mock it and set Messenger.OverrideDefault to the mock like this:
var mock = new Mock<IMessenger>();
Messenger.OverrideDefault((Messenger)mock.Object);
But I got an invalid cast error. Is the OverrideDefault method not for that purpose or more likely I'm using it incorrectly.
Or would I have an interface for the classes that are receiving the messages and mock those? All I really want to test is that a RelayCommand sends a message when it is called.
I just started to look at this myself. I'm a little surprised that Messenger.OverrideDefault doesn't take an IMessenger as a parameter. You have to inherit Messenger.
I suppose you could create a class that internally uses your mock object and then do a Verify.
[Test]
public void ShowSetup_SendsMessage_WhenShowSetupCommandCalled() {
Messenger.Reset();
MaintenanceViewModel target = new MainViewModel();
IMessenger mockMessenger = MockRepository.GenerateMock<IMessenger>();
mockMessenger.Expect(m => m.Send("Settings"));
TestMessenger testMessenger = new TestMessenger(mockMessenger);
Messenger.OverrideDefault(testMessenger);
bool wasCalled = false;
Messenger.Default.Register<NotificationMessage>(this, "Settings", (msg) => wasCalled = true);
target.ShowSetupCommand.Execute(null);
mockMessenger.VerifyAllExpectations();
}
You may or may not need a stub on the Register method.
The TestMessenger class:
public class TestMessenger : Messenger {
private IMessenger _mockMessenger;
public TestMessenger(IMessenger mock) {
_mockMessenger = mock;
}
public override void Register<TMessage>(object recipient, bool receiveDerivedMessagesToo, Action<TMessage> action) {
_mockMessenger.Register<TMessage>(recipient, receiveDerivedMessagesToo, action);
}
public override void Register<TMessage>(object recipient, Action<TMessage> action) {
_mockMessenger.Register<TMessage>(recipient, action);
}
public override void Send<TMessage, TTarget>(TMessage message) {
_mockMessenger.Send<TMessage, TTarget>(message);
}
public override void Send<TMessage>(TMessage message) {
_mockMessenger.Send<TMessage>(message);
}
public override void Unregister<TMessage>(object recipient, Action<TMessage> action) {
_mockMessenger.Unregister<TMessage>(recipient, action);
}
public override void Unregister<TMessage>(object recipient) {
_mockMessenger.Unregister<TMessage>(recipient);
}
public override void Unregister(object recipient) {
_mockMessenger.Unregister(recipient);
}
}
Another approach that using constructor injection you can see in this answer. I think it's better to use constructor injection instead of using static Messenger.Default. It's more robust approach cause dependency injection providing natural seam with which you can easily substitute dependencies in unit tests. If you try to substitute static member call, then you rely on internal implementation that obviously can change.
精彩评论