2012-07-19 26 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)); 
}