【问题标题】:How to unit test Prism INavigationAware.OnNavigatedTo with async calls如何使用异步调用对 Prism INavigationAware.OnNavigatedTo 进行单元测试
【发布时间】:2020-12-22 16:15:48
【问题描述】:

我们的很多 ViewModel-Unit-Tests 在 Arrange-Phase 创建一个 ViewModel,在 Act-Phase 调用 OnNavigatedTo() 并断言一些在 OnNavigatedTo 完成后应该发生的事情(例如,一些 Properties 包含某些值)。

当 OnNavigatedTo() 的实现包含异步方法调用(例如从后端加载数据)时,我们会遇到问题,因为 OnNavigatedTo 返回 void,我们无法等待它完成。

在我们的单元测试中,我们模拟了对后端的调用,因此它们会立即返回并且问题几乎不会出现。然而,我们有一个案例,正是这种情况导致构建服务器(在 Linux 上运行)出现问题,我怀疑这总是会产生一种竞争条件,这种情况在大多数情况下只是偶然发生的。

我们想出的一个解决方法是提供一个公共方法,该方法返回一个包含 OnNavigatedTo 实现并由单元测试使用的任务,但通常不是为了扩展被测系统的公共 API 表面为了测试。

在我看来,将所有代码移至 IInitializeAsync.InitializeAsync 不是一个选项,而且这两个生命周期挂钩并不等效,并且可能不会在每个页面导航上调用 InitializeAsync。

所以我的问题是:我们如何可靠地对 INavigationAware.OnNavigatedTo 中的代码进行单元测试,从而进行异步调用?

【问题讨论】:

  • 在某些情况下,您可以在调用被测主题后使用Task.Delay,以便在做出断言之前有足够的时间让异步内容完成。

标签: c# unit-testing mvvm xamarin.forms prism


【解决方案1】:

我们想出的一个解决方法是提供一个公共方法返回一个包含OnNavigatedTo 实现并由单元测试使用的任务

我会这样做,除了我会使用internal(如果夹具必须在另一个组件中,则使用InternalsVisibleTo)甚至private(如果您可以使夹具成为嵌套类)。

或者,定义您自己的 INavigatedToAsyncForTest(使用返回 Task 的方法)并显式实现它以限制这些方法的可发现性。

但为了测试而扩展被测系统的公共 API 表面通常不是一个好主意。

是的,但是使方法 internal 尖叫“这不是公共 API”,特别是如果类型本身是 internal(应该是哪个视图模型,除非您必须将视图放在不同的程序集中),所以您可以在一定程度上缓解这种情况。

【讨论】:

  • 谢谢!我们的测试驻留在一个单独的测试项目中。我喜欢 InternalsVisibleTo 的解决方案,所以我至少可以锁定这个 API 的使用。
猜你喜欢
  • 2016-03-19
  • 1970-01-01
  • 2023-03-06
  • 1970-01-01
  • 2013-03-15
  • 1970-01-01
  • 1970-01-01
  • 2013-01-22
  • 1970-01-01
相关资源
最近更新 更多