如何对具有多层子项的根ViewModel进行单元测试?

时间:2013-06-07 14:25:03

标签: c# wpf unit-testing mvvm moq

我在为特定的ViewModel编写测试时遇到困难,这个ViewModel将几个其他ViewModel及其子节点连接在一起。它是我应用程序中最复杂的ViewModel。

我的ViewModel的结构反映了视图的结构。它注射了孩子,孩子们注射了孩子。

模仿是非常费力的。

由于依赖链而导致模拟是耗时的。例如,假设我有结构MainViewModel.SubViewModel1.SubViewModel2,而不是我最终必须模拟多个图层,因为MainViewModel中的操作可能导致SubViewModel1需要检查SubViewModel2的可见性。

这是设计不佳的结果吗? 我的单元测试不正确吗? 是否有AutoMockers会递归模拟我注入的参数?

2 个答案:

答案 0 :(得分:2)

很容易说这是糟糕的设计,它也可能也是如此。

然而,有些情况可能需要这样做。如果你确定你的其中一个案件,那么你必须忍受它。如果它是你最复杂的VM,那么测试它将是你最复杂的测试是合乎逻辑的。

  • 对于功能测试,由于其中的操作将影响其他子孙VM的属性(根据您的依赖关系),您的测试是否有效应该测试所有这些,这意味着您不能也不应该真正嘲笑他们就像你这样做,你没有真正测试那个VM。
  • 现在进行单元测试,你只关心这个虚拟机,因此你的模拟应该只针对直接子节点依赖。即使逻辑需要大孩子,你也可以让模拟层VM模拟它并相应地返回结果。因此,在最多只有99%的情况下,您的测试虚拟机只有一层子项(排除总是适用于这些事情)

最后,我希望你的VM之间有一些接口结构,以帮助你相应地模拟VM。这将帮助您在这种情况下,就好像您在测试中使用IoC容器只注入模拟VM而不是实时VM。这可以是VM本身的接口,也可能是很多人喜欢将这些行为提取到服务中。

答案 1 :(得分:2)

你的Q2“我错误地进行单元测试”的答案是“可能”。单元测试是关于单独测试单元的。但有时很难做到。你有几个选择:

使SubViewModel1具有暴露SubViewModel2可见性的属性,这样,在测试MainViewModel时,您将仅模拟/存根SubViewModel1。当然,如果该属性确实有效,您将进行测试:)

现在,以上是从“纯粹”的观点出发。有时候,即使从OO设计的角度做正确的事情,这样做也是不切实际的。

所以,你可以尝试AutoFixture as an auto-mocking container,它会准备嵌套的模拟。

再次,检查你的设计,通常是你发现某些东西很难测试,可能它的构造不好,并且做得太多。