这是测试MVVM-Light Toolkit消息的可接受方式吗?

时间:2010-08-26 18:58:16

标签: unit-testing mvvm-light

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

我看到有一个IMessenger接口,我试图模仿它并将Messenger.OverrideDefault设置为这样的模拟:

var mock = new Mock<IMessenger>();      
Messenger.OverrideDefault((Messenger)mock.Object);

但是我收到了无效的施法错误。 OverrideDefault方法是不是出于那个目的,或者更可能是我错误地使用它。

或者我是否有接收消息的类的接口并嘲笑那些?我真正想测试的是RelayCommand在调用时发送消息。

2 个答案:

答案 0 :(得分:3)

我自己开始看这个。我对Messenger.OverrideDefault没有将IMessenger作为参数感到有点惊讶。你必须继承Messenger。

我想你可以创建一个内部使用模拟对象的类,然后进行验证。

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

您可能需要或可能不需要Register方法的存根。

TestMessenger类:

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

答案 1 :(得分:0)

使用构造函数注入的另一种方法,您可以在此answer中看到。我认为最好使用构造函数注入而不是使用静态Messenger.Default。它是更强大的方法导致依赖注入提供自然接缝,您可以在单元测试中轻松替换依赖项。如果您尝试替换静态成员调用,那么您依赖于显然可以更改的内部实现。