【问题标题】:Is it possible to write Prism apps such that they can be tested without the UI?是否可以编写 Prism 应用程序以便在没有 UI 的情况下对其进行测试?
【发布时间】:2011-12-05 09:50:42
【问题描述】:

免责声明:棱镜新手。我正在疯狂地阅读以弥补失去的时间:)

上下文:我需要为使用 Prism 构建的 WPF 应用程序编写自动化验收测试。

问题:我发现尝试在没有 UI 的情况下组合支持 ViewModel 和他们需要的一切是很复杂的。

我在这里可能错了... Prism 允许您使用命名占位符(区域)标记外壳。不同的模块(隔离单元)使用相应的 RegionNames 注册它们的视图。视图还依赖于通过 MEF/Unity 注入的 ViewModel(ctor 注入)。

  1. 显示视图
  2. 触发创建子视图(regionName => 视图注册表)
  3. 触发创建子视图模型(Mef ctor 注入)。

因此,编写应用程序被委托给 Prism(或更重要的是 View)。这似乎是一种视图优先的方法。这会在没有 UI 的情况下启动应用程序。使用 UI 进行测试很痛苦。

我正在寻找的是演示者优先方法,它在没有 UI 的情况下组成整个对象(ViewModel 和依赖项)图。

var viewModel = Someone.ComposeAndGet<ShellViewModel>();

Prism4 是否可以通过不同的方式编写应用程序,或者它是否不受支持?

[更新:2011 年 12 月]
http://compositewpf.codeplex.com/discussions/283065
发布在 prism 论坛上以获得更多信息;似乎这是不可能的。建议使用 UI 测试进行验收测试。 Prism 组成 UI;因此对视图有至关重要的依赖性。

【问题讨论】:

  • 好问题 - 自从我们在我们的解决方案中实施 PRISM 和 MVVM 以来,我一直对它有一种下沉的感觉。我们现在遇到了您描述的测试问题。看来 MVVM 已经被改装到 PRISM 中了,两者玩的不太好。导航是一个理想的例子——要在没有视图的情况下进行测试,我们需要纯粹在视图模型中保持导航状态,但是 PRISM 通过区域进行导航管道将我们硬连接到视图。在 ViewModel 中设置 RegionManagers 和 Regions,然后从 View 绑定到它们可能是一种方式 - 但可惜它似乎不起作用
  • @JamesClose - 是的,这是 Prism 团队(由于我们与 MS 的支持协议)提出的潜在途径之一。 Regions 也可以包含 ViewModels + ViewModels 可以包含 Regions。但是 MS 不支持它。你可以破解一些东西并让它工作..但是它不是 MS 会明确测试或保留未来版本的行为。他们说他们一直在听到类似的请求,但这不在他们的下一个功能队列之上。另一个差距w.r.t。 Prism docs 是 view-model first 的定义 = 来自 VM 的视图注入

标签: .net wpf prism-4


【解决方案1】:

我喜欢 Prism 框架,但我很少使用 Prism 的区域,因为我觉得它迫使我采用 View-First 方法。

我不喜欢使用 View-First,因为我觉得它消除了使用 MVVM 设计模式的一些优势,例如保持层分离和单元测试。如果您的视图负责创建您的视图模型,那么要测试您的视图模型,您需要创建视图来创建视图模型,或者您需要手动创建视图模型。

我还认为理想的 MVVM 应用程序应该允许您使用任何 UI 甚至命令行运行应用程序,并且通过使用区域我将 ViewModel 限制为 Prism 界面。

有时我仍会使用 Prism 的区域,但通常只用于启动页面(例如 TitleBarRegion、MenuRegion、ContentRegion)

【讨论】:

  • 正是我的感受。但是,如果我排除区域,棱镜有帮助吗?你会如何看待作文? MSDN 上几乎没有与此主题相关的任何文档。还是我错过了链接?
  • @Gishu 我喜欢使用 Prism 的 EventAggregatorNotificationObjectDelegateCommand。我已经使用了一点 MEF 注射,尽管我不会称自己为专家。我真正不喜欢使用的唯一部分是区域。
  • @Gishu 通常我通过ApplicationViewModel 处理导航,其中包含可用和当前页面(以及当前用户和错误消息等内容)。如果您有兴趣,我在这里写了一个示例:rachel53461.wordpress.com/2011/07/17/navigation-with-mvvm 实际上,我正在重写该帖子以使其更加清晰,并包含一个工作代码示例,并希望在下周末对其进行更新(提供圣诞购物不会妨碍)
  • 也许我做错了什么,但我使用 Prism 和它的区域采用 ViewModel-First 方法,我没有看到任何缺点。
  • 我不同意,棱镜区域可以让你做一些非常简洁的事情,我将我的视图注入到 AvalonDock.DocumentPane 中包含的一个区域中,并使用一点 RegionAdater 魔法将视图放入滚动查看器中,然后在一个新选项卡,然后将其推送到 DocumentPane 中。像魅力一样工作,感觉干净。
【解决方案2】:

我不完全确定我理解这个问题,但是要对 prism 应用程序进行单元测试:

您可以使用 ServiceLocator 来检索 ViewModel:

MainViewModel mainVM = ServiceLocator.Current.GetInstance<MainViewModel>(); //That will "compose and get"

然后你可以随意对它进行单元测试。

也就是说,Prism 和一般的 MVVM 将大部分职责委派给 VM。视图只是数据的表示,它不包含任何逻辑。
虚拟机保存数据/逻辑并对它进行更改,而不知道它实际绑定到哪个视图。

希望这会有所帮助 =)

【讨论】:

  • 我正在考虑编写验收测试。这意味着如果 Shell 包含 2 个区域(比如一个树和一个列表,比如 Windows 资源管理器),那么显示视图就是触发创建 TreeVM 和 ListVM 的原因。如果我不显示父视图,则永远不会创建视图模型。简而言之,我想在不调出 UI 的情况下触发 ViewModel 图的组合。
  • 所以你想知道视图/视图模型是什么时候创建的?如果您只要求 VM,我谈论的 ServiceLocator 不会创建任何 UI。
  • 当我运行应用程序时,显示视图会递归地触发创建子视图和视图模型,并且一切正常。在我的测试中,由于我不会调出父视图,因此不会创建子视图模型,除非我为此编写特定代码(这将是一个维护麻烦 - 例如有人添加/删除一个区域)。在上面的示例中,我想要一个创建 ShellViewModel 的方法,然后触发创建 TreeVM 和 ListVM没有 UI。基本上我想在 UI 下编写所有内容,可以说剥离 UI。
  • 您面临的问题是,在 MVVM/Prism 中,视图可以接受几种不同的视图模型,而视图模型不知道它们的视图。这实现了松散耦合。同时,这也意味着做自己想做的事,很可能会涉及到反思……
  • 好像没那么简单; Prism 在幕后做了很多事情,例如如果 ActiveView 从 View1 更改为 View2,它可能会转储所有以 View1 作为图根的对象,并将新的对象图带入内存。现在,Shell 可能会引发将由 View2VM 处理的事件。如果我没有 UI,我基本上必须通过代码来模拟所有这些——这是不可行的。例如如果我忘记编写代码来实例化 View2VM 并且它在正确的时间进行 minion,测试可能会报告错误的失败。
猜你喜欢
  • 2018-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多