Has anyone successfully mocked the Socket class in .NET?

后端 未结 5 1026
深忆病人
深忆病人 2021-01-02 08:38

I\'m trying to mock out the System.net.Sockets.Socket class in C# - I tried using NUnit mocks but it can\'t mock concrete classes. I also tried using Rhino Mocks but it see

相关标签:
5条回答
  • 2021-01-02 08:42

    The reason you get a SocketException when you call the Send method is because Send is not an overridable method. For RhinoMocks to be able to mock the behavior of a property or method, it has to either be defined in an interface (which we then create our mock off) or is overridable.

    Your only solution to this is to create a mockable wrapper class (as suggested by thinkzig).

    0 讨论(0)
  • 2021-01-02 08:52

    I've created an example console application using the method thinkzig suggests (an adapter class for Socket). It uses RhinoMocks and NUnit. You can download it here: How to mock System.Net.Sockets.Socket.

    0 讨论(0)
  • 2021-01-02 09:04

    The above class only Mocks your Send Method. This actually mocks a Socket. It Inherits all of Socket and then Implements the ISocket interface. ISocket needs to implement the signatures of any Socket methods or properties you need to mock

    //internal because only used for test code
    internal class SocketWrapper : Socket, ISocket
    {
        /// <summary>
        /// Web Socket
        /// </summary>
        public SocketWrapper():base(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
        {
        }
    
        //use all features of base Socket
    }
    

    The interface looks like this with two methods declined:

    public interface ISocket
    {
        void Connect(IPAddress address, int port);
        int Send(byte[] buffer, int offset, int size, SocketFlags socketFlags, out SocketError errorCode);
    }
    

    The Class that uses them has 2 constructors. One injects an ISocket for testing and then one that makes it's own Socket that the application uses.

    public class HTTPRequestFactory3
    {
    internal ISocket _socket;
    
    
        /// <summary>
        /// Creates a socket and sends/receives information.  Used for mocking to inject ISocket
        /// </summary>
        internal HTTPRequestFactory3(ISocket TheSocket)
        {
         _socket = TheSocket as ISocket;
         this.Setup();
        }
    
        /// <summary>
        /// Self Injects a new Socket.
        /// </summary>
        public  HTTPRequestFactory3()
        {
            SocketWrapper theSocket = new SocketWrapper();
            _socket = theSocket as ISocket;
            this.Setup();
        }
    }
    

    Then your tests can create a ISocket, set up expectations and verify them running all the same code the above class will use with a real socket. This test validates that section code.

       [Test]
       public void NewSocketFactoryCreatesSocketDefaultConstructor()
            {
                webRequestFactory = new HTTPRequestFactory3();
                Assert.NotNull(webRequestFactory._socket);
                Socket testSocket = webRequestFactory._socket as Socket;
                Assert.IsInstanceOf<Socket>(testSocket);
            }
    
    0 讨论(0)
  • 2021-01-02 09:06

    Whenever I run into these kinds of problems with Moq I end up creating an interface to abstract away the thing I can't mock.

    So in your instance you might have an ISocket interface that implements the Send method. Then have your mocking framework mock that instead.

    In your actual code, you'd have a class like this

    public class MySocket : ISocket
    {
      System.Net.Sockets.Socket _socket;
    
      public void MySocket(System.Net.Sockets.Socket theSocket)
      {
        _socket = theSocket;
      }
    
      public virtual void Send(byte[] stuffToSend)
      {
        _socket.Send(stuffToSend);
      }
    
    }
    

    Not sure if that meets your needs, but it's an option.

    0 讨论(0)
  • 2021-01-02 09:06

    You'd better to create an interface and mock it in your test, and implement a wrapper class in your code, that forward all method calls to .NET socket as thinkzig said. Look at this link, it's same issue: How do you mock out the file system in C# for unit testing?

    0 讨论(0)
提交回复
热议问题