Caliburn.Micro WindowManager 的模拟 rootView

Mock rootView of Caliburn.Micro WindowManager

鉴于我有这样的方法:

public void ShowDialog()
{
  TestViewModel vm = new TestViewModel();
  _windowManager.ShowDialog(vm);
  DialogResultTest = vm.CoolText;
}

现在我想写一个测试。在该测试中,我想将准备好的 TestViewModel 注入 ShowDialog(vm) 方法。我的代码如下所示:

[Test]
public void TestShowDialog()
{
  TestViewModel mockVM = new TestViewModel();
  mockVM.CoolText = "test";

  Mock<IWindowManager> wmMock = new Mock<IWindowManager>();
  wmMockSetup(w => w.ShowDialog(It.IsAny<object>(), It.IsAny<object>(), It.IsAny<IDictionary<string, object>>()))
                   .Returns(true)
                   .Callback<object, object, IDictionary<string, object>>((vm, obj, dic) =>
                   {
                     vm = mockVM;
                   });

  MainViewModel mainVM = new MainViewModel(wmMock.Object);
  mainVM.ShowDialog();
  Assert.That(mainVM.DialogResultText, Is.EqualTo("test");
}

问题是,我在测试中设置的 CoolText 在实际 _windowManager.ShowDialog(vm) 调用后消失了(DialogResultText 是空的)。似乎 mockVM 仅用于 _windowManager.ShowDialog(vm) 的实际调用,但在之后被原来的 vm 替换。

有办法解决这个问题吗?

您正在手动实例化被测方法中的 TestViewModel ,因此您无法在测试期间轻松操纵其行为。您必须能够像 IWindowManager

一样将其作为显式依赖项注入到目标 class 中

另一种方法是使用回调来更新在调用模拟成员时作为参数传入的实际视图模型的 属性。

//Arrange
var expected = "test";
var wmMock = new Mock<IWindowManager>();
wmMock.Setup(w => 
    w.ShowDialog(It.IsAny<object>(), It.IsAny<object>(), It.IsAny<IDictionary<string, object>>()))
      .Returns(true)
      .Callback<object, object, IDictionary<string, object>>((obj1, obj2, dic) => {
          var vm = obj1 as TestViewModel;
          if(vm ! = null) 
              vm.CoolText = expected;
      });

var mainVM = new MainViewModel(wmMock.Object);

//Act
mainVM.ShowDialog();

//Assert
Assert.That(mainVM.DialogResultText, Is.EqualTo(expected);