Win10 UWP,Prism/Unity 和单元测试加上 Class 库,静默失败

Win10 UWP, Prism/Unity and Unit Tests plus Class Libraries, silent failure

基本布局目前是一个简单的应用程序。没什么特别的,我在 App.Views 命名空间中有视图,在 App.ViewModels 命名空间中有我的视图模型。 ViewModels 通过 XAML 指令自动连接到视图:

xmlns:prismMvvm="using:Prism.Windows.Mvvm"
prismMvvm:ViewModelLocator.AutoWireViewModel="True"

所以,基本上,这是可行的。然后我想利用 Unity 的 IoC / DependencyInjection 进行一些单元测试。

通常的方法是简单地向现有应用添加一个 Windows 10 单元测试应用,并在单元测试应用中引用后者。

这会在执行单元测试时崩溃,因为您似乎无法从除 Application 之外的任何其他内容中派生 App class。 IE。这有效:

public sealed partial class App : Application

这不是:

public sealed partial class App : PrismUnityApplication

这可能也不是 Prism 的错,Microsoft 必须最终解决这些问题。

现在,建议的解决方法是将您想要进行单元测试的任何内容简单地放入 class 库中,并从单元测试应用程序中引用该库。这适用于单元测试。它也适用于模型。

但是,我天真的方法对 ViewModel 不起作用。与以前一样,ViewModel classes 仍然位于 App.ViewModels 命名空间下,只是它们现在位于 Class 库中。我可以在主应用程序中以编程方式访问它们就好了。但是在 运行 程序上,AutoWiring 无声无息地失败了。

即使我这样做了,它仍然不起作用:

ViewModelLocationProvider.Register(typeof(MainPage).ToString(), () => new ViewModels.MainPageViewModel());

我对所涉及的技术还不是很熟悉,所以如果没有实际错误,我有点不知所措。

编辑:只是为了增加神秘感——这段代码确实有效,无论 ViewModel 是驻留在主应用程序还是 class 库中:

var x = Container.Resolve(typeof(ExamplePageViewModel)) as ExamplePageViewModel;

你是对的,这通常是 UWP 应用程序可测试性的限制。 UWP 应用的可测试性目前还不完善。为了解决第一个问题,您需要将 BindableAttribute 添加到您的应用程序 class:

[Bindable]
sealed partial class App : PrismUnityApplication
{

}

就将您的 Views/ViewModels 拉出到单独的程序集中而言,此问题是由于 UWP 如何处理加载类型形成单独的程序集。 None 越少,这不应该阻止您测试 ViewModel。您可以使用常规 class 库来测试您的 ViewModel 逻辑。您将模拟您的依赖项。您不应该创建视图的实例来测试您的视图模型。因此 ViewModelLocator 不再是问题。

我们遇到了与您相同的问题,测试静默失败。 当我们查看测试输出 window 时,我们看到了这个:

App activation failed.
Failed to initialize client proxy: could not connect to test process.

在继承了 [PrismUnityApplication] 的 [UnitTestApp] 中,我们覆盖了 [ConfigureContainer] 方法,并在容器上设置模拟,而不是设置真正的 classes,即

UnitTestApp.Current.Container.RegisterInstance(myMock.Object, new ContainerControlledLifetimeManager());

您还可以在每个测试 class' 构造函数中设置容器 这样我们就得到了我们的测试 运行 而没有静默失败。

静默失败似乎是由于在 UnitTestApp class 的上下文中调用了实际 App class 的容器 - 但我无法 100% 确认