调用回调方法时无法访问处置对象

问题描述:

我有一个双工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被阻止,所以不可能一个接一个地绑定到同一个套接字 –

我终于找到了问题。我觉得有点愚蠢,但事实上,在服务实现中,我没有正确注销OnMessage,所以当事件被触发时,以前的服务实例试图与已经关闭的客户端进行通信。

+0

很高兴你发现它:) –