4

我正在运行托管在 Windows 服务中的 WCF 服务;WCF 服务的依赖项是通过 Unity 注入的,这一切都很好。因此,该服务也很容易为其编写单元测试。

最近,我向服务中添加了使用 OperationContext 检查传入消息的功能。不幸的是,由于微软对密封和/或静态类的喜爱以及缺乏接口和/或虚拟方法,这反而使服务的可测试性失去了意义。

所以在这种情况下,我求助于 .NET 人最喜欢的工具,一个包装类。由于这是一个常见问题,因此有人已经为我们完成了艰苦的工作。因此,这为我的 WCF 服务添加了一个新的依赖项,即 IOperationContext 的实现。这对我的单元测试来说没问题,NSubstitute 是我选择的模拟框架(就像 Moq,但没有.Object.

但是,当我尝试真正启动服务时,我遇到了以下问题 - 正在包装的 OperationContext 在 IoC 容器注册完成时尚未初始化。我的初始化代码(在这里使用 Unity)是:

container.RegisterType<IOperationContext, OperationContextWrapper>(new InjectionConstructor(OperationContext.Current));

但是此时,OperationContext.Currentnull,所以 Unity 立即抛出异常,我的 40 岁之前退休的梦想付诸东流。

所以,问题是:如何让 WCF 与 DI 和 Wrapped 很好地配合使用OperationContext

4

3 回答 3

2

也许我不明白,但我不确定你为什么要将 OperationContext.Current 注入到你的包装器中。如果 OperationContextWrapper 正在包装 OperationContext,那么为什么不让它的实现直接与 OperationContext.Current 交互呢?我认为您试图保持可测试的代码不是 OperationContextWrapper,而是通过 IOperationContext 接口依赖于它的代码?那么谁在乎 OperationContextWrapper 做什么呢?

于 2011-07-13T04:50:13.520 回答
1

OperationContext.Current是一个可设置的属性。您可以将测试初始化​​更改为

OperationContext.Current = new OperationContextWrapper();

并让它这样工作吗?如果您需要统一使用它,您还可以:

var oc = new OperationContextWrapper();
OperationContext.Current = oc;
container.RegisterInstance<IOperationContext>(oc);
于 2011-07-13T00:01:17.447 回答
1

您还可以使用 Microsoft Fakes :

using (ShimsContext.Create()) 
{
ShimOperationContext shimOperationContext = new
ShimOperationContext(); shimOperationContext.SessionIdGet = () => "sessionId";

OperationContext.Current = shimOperationContext;
}
于 2014-02-21T16:35:02.733 回答