Помощь в реальном мире TDD с использованием Java - PullRequest
5 голосов
/ 15 марта 2011

Сейчас мне нужна помощь, чтобы использовать TDD для примера из реальной жизни.Большинство шоу слишком просты и не показывают, как тестировать и перефакторизовать более сложные классы.Вот пример кода, который использует как поток, так и сетевой сокет.Может ли кто-нибудь объяснить, как создать изолированный модульный тест для такого класса?Спасибо.

public class BaseHandler  extends Thread {
  protected Socket mClientSocket;
  protected BufferedReader is = null;
  protected BufferedWriter os = null;
  private Logger mLogger = Logger.getLogger(WebTestController.class.getName());
  protected WebTestController mWebTestController;

  /*********************************************************************
   * 
   * @param piPort - int port to listen on
   */
  public BaseHandler(){
  }


  /*********************************************************************** cleanup
   * Ensure sockets are closed as to not run into bind errors
   */
  protected void cleanup() {
    try {
      if (is != null)
        is.close();
      if (os != null)
        os.close();
      if (mClientSocket != null)
        mClientSocket.close();
    }
    catch (IOException e) {
        e.printStackTrace();
    }
    mLogger.info("cleaning up a socket");
  }

  /***********************************************************************************
   * Sends a message to the current socket
   * @param pMessage
   */
  protected void writeToSocket(String pMessage){
      try {
          os = new BufferedWriter(
            new OutputStreamWriter(mClientSocket.getOutputStream()));

        }
        catch (IOException e) {
          e.printStackTrace();
          cleanup();
          return;
        }
        try {
            os.write(pMessage, 0, pMessage.length());
            os.flush();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        cleanup();
  }

}

Ответы [ 5 ]

5 голосов
/ 15 марта 2011

Не создавайте такие классы.

Было бы лучше разбить вашу логику на часть, связанную с IO, и часть, связанную с параллелизмом. Затем часть, относящуюся к IO, можно протестировать, например, с помощью фиктивного сокета.

Однако проверка логики, связанной с параллелизмом, была бы более сложной. Это зависит от поведения, которого вы хотите достичь.

5 голосов
/ 15 марта 2011

Вот несколько практических советов, которые помогут вам решить проблемы с тестированием:

  1. Не заставляйте ваш класс наследовать Thread.Вместо этого сделайте его Runnable, потому что вы можете тестировать Runnable изолированно.
  2. Используйте внедрение зависимостей , чтобы вы могли заменить Logger и WebTestController тестовыми версиями (см. «Mocking»).
  3. Удалите из кода что-нибудь, что еще ничего не делает.Затем проверьте, что у вас есть.Добавляйте новые материалы только тогда, когда все, что вы реализовали, работает и имеет действительные тесты, чтобы доказать это

Однако я настоятельно рекомендую прочитать хорошую книгу о TDD и модульном тестировании.Простые уроки просто - просто.Они не охватывают сложные случаи, с которыми вы столкнетесь в реальной жизни.Вполне возможно использовать TDD в реальной жизни, но для этого нужны некоторые знания - как программирование.

1 голос
/ 15 марта 2011

Этот класс не учитывает SRP (принцип единой ответственности). Ваш класс выполняет слишком много логики. Вместо этого вы должны разделить этот класс на несколько меньших. Затем вы обычно внедряете эти классы с помощью Spring или другой платформы IoC.

Если бы вы разделили класс, вы заметили бы, что тестирование будет намного проще. Вы можете предоставить фиктивные объекты для этих компонентов и вводить их по своему усмотрению в каждом тестовом примере, так как он подходит вам лучше всего.

1 голос
/ 15 марта 2011

Код не «использует» поток, это просто класс, полученный из java.lang.Thread.Ничто не мешает вам вызывать метод run() напрямую, ведь вы тестируете свой класс, а не функциональность в java.lang.Thread.

На самом деле вы хотите протестировать методы cleanup() и writeToSocketпоэтому нет необходимости также вызывать метод run().

Просто создайте подкласс BaseHandler, инициализируйте своих членов в этом подклассе с какими-то фиктивными объектами, и все готово.

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

1 голос
/ 15 марта 2011

AFAIK, вы должны начать с Тестового случая в Test Drive Development. Я предлагаю вам начать с теста, который этот класс должен пройти первым, и рассматривать его как прототип.

Вам нужно будет создать класс или подкласс, который откроет Socket для фиктивного ServerSocket и отправит ему сообщения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...