Кто-нибудь успешно издевался над классом Socket в.NET?

Я пытаюсь смоделировать класс System.net.Sockets.Socket в C# - я пробовал использовать макеты NUnit, но он не может имитировать конкретные классы. Я также пытался использовать Rhino Mocks, но, похоже, он использовал реальную версию класса, потому что он вызывал исключение SocketException при вызове Send(byte[]). Кто-нибудь успешно создал и использовал макет Socket, используя какой-либо фреймворк?

5 ответов

Решение

Всякий раз, когда я сталкиваюсь с подобными проблемами с Moq, я заканчиваю тем, что создаю интерфейс, чтобы абстрагироваться от того, что я не могу высмеять.

Так что в вашем случае у вас может быть интерфейс ISocket, который реализует метод Send. Тогда имейте свои насмешливые рамки вместо этого.

В вашем реальном коде у вас будет такой класс

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);
  }

}

Не уверен, что это соответствует вашим потребностям, но это вариант.

Вышеуказанный класс только проверяет ваш метод отправки. Это на самом деле издевается над сокетом. Он наследует весь сокет, а затем реализует интерфейс ISocket. ISocket должен реализовывать сигнатуры любых методов или свойств Socket, которые вам нужно смоделировать

//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
}

Интерфейс выглядит так с двумя отклоненными методами:

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

Класс, который их использует, имеет 2 конструктора. Один вводит ISocket для тестирования, а затем тот, который создает свой собственный Socket, который использует приложение.

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();
    }
}

Затем ваши тесты могут создать ISocket, настроить ожидания и убедиться, что они выполняют весь код, который приведенный выше класс будет использовать с реальным сокетом. Этот тест проверяет этот код раздела.

   [Test]
   public void NewSocketFactoryCreatesSocketDefaultConstructor()
        {
            webRequestFactory = new HTTPRequestFactory3();
            Assert.NotNull(webRequestFactory._socket);
            Socket testSocket = webRequestFactory._socket as Socket;
            Assert.IsInstanceOf<Socket>(testSocket);
        }

Причина, по которой вы получаете SocketException при вызове метода Send, заключается в том, что Send не является перезаписываемым методом. Чтобы RhinoMocks мог имитировать поведение свойства или метода, он должен быть либо определен в интерфейсе (который мы затем создаем с помощью нашего макета), либо его можно переопределить.

Ваше единственное решение для этого - создать класс с надёжной оболочкой (как предполагает thinkzig).

Я создал пример консольного приложения, используя метод thinkzig (класс адаптера для Socket). Он использует RhinoMocks и NUnit. Вы можете скачать его здесь: Как издеваться над System.Net.Sockets.Socket.

Вам лучше создать интерфейс и смоделировать его в своем тесте, а также реализовать класс-оболочку в своем коде, который перенаправляет все вызовы методов в сокет.NET, как сказал thinkzig. Посмотрите на эту ссылку, это та же проблема: как вы макете файловую систему в C# для модульного тестирования?

Другие вопросы по тегам