如何在 NUnit 中替换 Prism ContainerLocator.Container

Posted

技术标签:

【中文标题】如何在 NUnit 中替换 Prism ContainerLocator.Container【英文标题】:How to substitute Prism ContainerLocator.Container in NUnit 【发布时间】:2021-12-22 22:15:44 【问题描述】:

我在测试中的班级中有以下代码:

  devices = ContainerLocator.Container.Resolve<IDevicesList>();           [1]

在我正在尝试编写的测试方法中:

 var fakeDeviceList = Substitute.For<IDevicesList>();
 Substitute.For<IContainerProvider>().Resolve<IDevicesList>().Returns(fakeDeviceList);

但我在 [1] 行中遇到了 ContainerLocator.Container 的空引用异常。 我试过用

var provider = Substitute.For<IContainerProvider>();
ContainerLocator.Container.Returns(provider);
provider.Resolve<IDevicesList>().Returns(fakeDeviceList);

但在测试运行时出现异常:

Message: 
NSubstitute.Exceptions.CouldNotSetReturnDueToNoLastCallException : Could not find a call to return from.

所以我的问题是如何替换ContainerLocator.Container?提前谢谢你。

【问题讨论】:

【参考方案1】:

我在测试中的班级中有以下代码:

devices = ContainerLocator.Container.Resolve&lt;IDevicesList&gt;();

这就是你不注入容器的原因。事实上,除了在注册阶段和对Resolve 的初始调用之外,您完全避免使用容器。

所以我的问题是如何替换ContainerLocator.Container

答案是:你没有

应该做的是让容器通过注入你真正想要的东西来完成解析工作,而不是万能的容器。

internal class MyService

    public MyService( IDeviceList devices )
    
    

internal class MyService

    public MyService( IEnumerable<IDevice> devices )
    
    

internal class MyService

    public MyService( Lazy<IEnumerable<IDevice>> devices )
    
    

internal class MyService

    public MyService( IEnumerable<Lazy<IDevice>> devices )
    
    

注入Lazy&lt;IEnumerable&gt;IEnumerable&lt;Lazy&gt; 之间的区别很细微,取决于所使用的实际容器,在这种情况下IContainerProvider 的行为通常是未定义的。

无论如何,您可以通过这种方式轻松注入模拟设备,而无需在测试期间模拟容器甚至使用真实容器。

【讨论】:

以上是关于如何在 NUnit 中替换 Prism ContainerLocator.Container的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 NUnit 3 在 Atlassian Bamboo 中运行 NUnit Runner?

从 Prism 7 迁移到 Prism 8

Prism.WPF -- Prism框架使用(上)

如何 File.Exists 在 Nunit 测试中

如何在需要括号的 NUnit 中编写流畅的约束

Prism:如何在区域中注入视图模型实例?