You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Caliburn.Micro WindowManager测试:Mock ViewModel注入失效问题

解决Mock WindowManager时ViewModel属性丢失的问题

你的问题核心在于C#的参数传递机制:你在Mock的Callback里尝试把vm替换成mockVM,但这只是修改了参数的副本,根本影响不到原方法里创建的那个TestViewModel实例。咱们一步步来解决:

为什么原来的测试无效?

原方法ShowDialog里是自己new了一个TestViewModel,然后把这个实例的引用传给_windowManager.ShowDialog。在你的Mock回调里,vm是这个引用的副本——你把副本指向mockVM,原方法里的vm变量还是牢牢指向原来的实例,所以后续DialogResultTest = vm.CoolText拿的还是原实例的空值。


解决方案1:重构原方法,支持ViewModel注入(推荐)

这是最符合可测试性原则的做法,让ShowDialog支持传入ViewModel(用可选参数保持原有调用的兼容性):

// 重构后的ShowDialog方法
public void ShowDialog(TestViewModel vm = null) { 
    // 如果没传入vm,就创建新的,保持原有逻辑
    vm = vm ?? new TestViewModel(); 
    _windowManager.ShowDialog(vm); 
    DialogResultTest = vm.CoolText; 
}

然后测试代码就可以直接传入你预先准备好的mockVM,不需要在Callback里折腾:

[Test] 
public void TestShowDialog() { 
    // 准备测试用的ViewModel
    TestViewModel mockVM = new TestViewModel(); 
    mockVM.CoolText = "test"; 

    // Mock WindowManager
    Mock<IWindowManager> wmMock = new Mock<IWindowManager>(); 
    wmMock.Setup(w => w.ShowDialog(mockVM, It.IsAny<object>(), It.IsAny<IDictionary<string, object>>()))
          .Returns(true); 

    // 实例化主ViewModel并测试
    MainViewModel mainVM = new MainViewModel(wmMock.Object); 
    mainVM.ShowDialog(mockVM); 
    Assert.That(mainVM.DialogResultText, Is.EqualTo("test")); 
}

解决方案2:不重构原方法,修改传入实例的属性(临时方案)

如果因为项目限制不能修改原方法,那可以在Mock的Callback里直接修改传入的原ViewModel实例的属性,而不是替换整个对象:

[Test] 
public void TestShowDialog() { 
    Mock<IWindowManager> wmMock = new Mock<IWindowManager>(); 
    
    // 在Callback里修改传入的ViewModel的CoolText属性
    wmMock.Setup(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) => { 
              // 把传入的object转成TestViewModel,然后设置属性
              if (vm is TestViewModel targetVm) {
                  targetVm.CoolText = "test";
              }
          }); 

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

这样,原方法里创建的TestViewModel在调用ShowDialog后,其CoolText会被回调修改,后续DialogResultTest就能拿到正确的值了。


内容的提问来源于stack exchange,提问作者Tim Kathete Stadler

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:43:29