2017-07-27 96 views
0

我有一個雙工TCP IP WCF服務。我目前正在對它進行單元測試。調用回調方法時無法訪問處置對象

在我的測試中,我設置了一個新的服務器,創建一個新的ChannelFactory,創建InstanceContext並進行調用。

然後,我觸發事件(它在服務器端的模擬),並且服務器給我這個例外,當它試圖達到的客戶:在mscorlib程序「System.ObjectDisposedException」:

拋出異常.dll 附加信息:無法訪問處置的對象。

重要的一點,只有當我在一行中運行所有測試(按順序執行但在相同的執行中)時,纔會發生這種情況。

沒有什麼特別之處我的服務:

[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IMyServiceCallback))] 
public interface IMyService{ 
    [OperationContract] 
    void SomeVariousMethods(); 
} 

[ServiceContract] 
public interface IMyServiceCallback 
{ 
    [OperationContract] 
    void HandleMessageFromServer(String message); 
} 


[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)] 
public class MyService : IMyService{ 
    public MyService(ISomeServerComponent component){ 
     component.OnMessage += OnMessageReceived; 
    } 

    public void SomeVariousMethods(){ 
     //... 
    } 

    private void OnMessageReceived(object sender, EventArgs<String> e){ 
     IMyServiceCallback callback = OperationContext.Current.GetCallbackChannel<IMyServiceCallback>(); 
     callBack.HandleMessageFromServer(e.Data);//Crash here 
    } 
} 

這裏是我當前如何單元測試它(不完全是,我有很多的這個已經在一些助手被提取:

[TestFixture] 
public class MyServiceTest:IMyServiceCallback{ 

    private Mock<ISomeServerComponent> _mock; 

    [OneTimeSetUp] 
    public void Setup(){ 
     //... Creating a mock for the ISomeServerComponent that the MyService receives 
    } 

    [Test] 
    public void TestSomeVariousMethods(){ 
     string serviceName = nameof(TestSomeVariousMethods); 
     using(ServiceHost host = CreateServer(_mock.Object,serviceName)){ 
      using (IMyService service = CreateClient(serviceName, this)){ 
       service.SomeVariousMethods(); 
      } 
     } 
    } 

    [Test] 
    public void TestCallback(){ 
     string serviceName = nameof(TestSomeVariousMethods); 
     using(ServiceHost host = CreateServer(_mock.Object,serviceName)){ 
      using (IMyService service = CreateClient(serviceName, this)){ 
       _mock.TriggerCallBack(); 
       //Assert-that-the-flag-has-been-set 
      } 
     } 
    } 

    public void HandleMessageFromServer(String msg){ 
     //Flag that this method has been called 
    } 




    private ServiceHost CreateServer(ISomeServerComponent mock, string serviceName){ 
     UnityServiceHost serviceHost = new UnityServiceHost(m_container);//This extends ServiceHost to be able to inject some objects to my services 
     NetTcpBinding binding = new NetTcpBinding(SecurityMode.None); 
     binding.ReliableSession.Enabled = true; 
     binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.None; 
     binding.MaxBufferPoolSize = Int64.MaxValue; 
     binding.MaxBufferSize = Int32.MaxValue; 
     binding.MaxReceivedMessageSize = Int32.MaxValue; 

     Uri uri = new Uri(String.Format("net.tcp://{0}:{1}/{2}", IPAddress.Any, 9999, serviceName)); 

     ServiceEndpoint serviceEndpoint = new ServiceEndpoint(ContractDescription.GetContract(typeof(IMyService)), binding, uri); 
     serviceEndpoint.EndpointBehaviors.Add(new ProtoEndpointBehavior()); 

     serviceHost.AddServiceEndpoint(serviceEndpoint); 
     return serviceHost; 
    } 

    private IMyService CreateClient(string serviceName, IMyServiceCallback callback){ 
     UnityServiceHost serviceHost = new UnityServiceHost(m_container);//This extends ServiceHost to be able to inject some objects to my services 
     NetTcpBinding binding = new NetTcpBinding(SecurityMode.None); 
     binding.ReliableSession.Enabled = true; 
     binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.None; 
     binding.MaxBufferPoolSize = Int64.MaxValue; 
     binding.MaxBufferSize = Int32.MaxValue; 
     binding.MaxReceivedMessageSize = Int32.MaxValue; 

     Uri uri = new Uri(String.Format("net.tcp://{0}:{1}/{2}", IPAddress.Loopback, 9999, serviceName)); 


     InstanceContext context = new InstanceContext(callBack); 
     DuplexChannelFactory channelFactory = new DuplexChannelFactory<T>(context, binding, new EndpointAddress(uri)); 
     return channelFactory.CreateChannel() 
    } 
} 

有趣的是,所有這一切的時候,我只運行TestCallback測試工作,但如果我運行的類的所有測試,它失敗了,就像如果第二次,InstanceContext沒有正確創建回調。

任何想法如何避免這種情況?

+0

我只是通過你的代碼策劃的,但是當涉及到tcp時,你會得到對象處置異常,特別是當套接字沒有正確關閉時 –

+0

@EmrahSüngü那麼,我已經在我的所有處理中放置了一些斷點,一切都正常關閉。我試着重複使用相同的「透明代理」來進行第二次單元測試的回調(並且在第二次測試運行時,第一個InstanceContext已經發布了) – J4N

+0

@是測試一個接一個運行還是st同一時間?如果在同一時間,因爲tcp被阻止,所以不可能一個接一個地綁定到同一個套接字 –

回答

2

我終於找到了問題。我覺得有點愚蠢,但事實上,在服務實現中,我沒有正確註銷OnMessage,所以當事件被觸發時,以前的服務實例試圖與已經關閉的客戶端進行通信。

+0

很高興你發現它:) –