2012-07-19 58 views
4

我想单元测试我的自定义ServiceHostFactory。不幸的是,我打电话CreateServiceHost当得到这个InvalidOperationException在单元测试中托管WCF服务

“ServiceHostFactory.CreateServiceHost”不能在当前的托管环境中调用。此API要求将调用应用程序托管在IIS或WAS中。

我可以通过重构我的类来解决此问题,以便公开可以由单元测试直接调用的公共方法,而不是使用其继承的公共接口;我讨厌为了单元测试而改变我的界面。我还看到另一个SO建议产生卡西尼主机的答案,但我不愿意以这种方式使我的单元测试复杂化。

有没有办法解决这个ServiceHostFactory限制而不诉诸于这些措施?

回答

5

我想出了这个问题。在我的自定义ServiceHostFactory中,我只覆盖了受保护的方法CreateServiceHost(Type serviceType, Uri[] baseAddresses)。通过重写公众的CreateServiceHost(string constructorString, Uri[] baseAddresses)方法,我能够毫无问题地构建服务主机工厂。

前:

public class MyServiceHostFactory : ServiceHostFactory 
{ 
    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses) 
    { 
     // ... 
    } 
} 

后:

public class MyServiceHostFactory : ServiceHostFactory 
{ 
    public override ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses) 
    { 
     return this.CreateServiceHost(typeof(MyService), baseAddresses); 
    } 

    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses) 
    { 
     // ... 
    } 
} 
1

这是我解决这个问题(我不是100%肯定我们是否应该这样做)。

在单元测试夹具的建立,建立一个托管环境(NUnit的例子):

[TestFixtureSetUp] 
public void TestFixtureSetup() 
{ 
    if(!HostingEnvironment.IsHosted) 
    { 
     // The instance constructor hooks up the singleton hosting environment, ewww... 
     new HostingEnvironment(); 

     // Check the hosting environment is fully initialized 
     ServiceHostingEnvironment.EnsureInitialized(); 
    } 
} 

那么你应当可以自由使用自定义ServiceHostFactory从单元测试中:

[Test] 
public void ServiceHostIsCorrect() 
{ 
    // Arrange 
    var serviceType = typeof (string); 
    var factory = new UnityServiceHostFactory(); 

    // Act 
    var serviceHost = factory.CreateServiceHost(serviceType.AssemblyQualifiedName, new Uri[] {}); 

    // Assert 
    Expect(serviceHost, Is.TypeOf<UnityServiceHost>()); 
    var unityServiceHost = (UnityServiceHost)serviceHost; 
    Expect(unityServiceHost.Description.ServiceType, Is.EqualTo(serviceType)); 
}