Как разработать приватный / финальный метод, доступный для насмешек? - PullRequest
1 голос
/ 15 ноября 2010

Это класс, который я должен проверить:

public class Downloader {
  public String download(String uri) {
    HttpClient client = this.getHttpClient();
    client.setURI(uri);
    return client.get();
  }
  private HttpClient getHttpClient() {
    HttpClient client = new HttpClient();
    // + some config
    return client;
  }
}

Очень просто. Теперь я хочу проверить его поведение, когда getHttpClient() выдает исключение. Однако я не могу издеваться над этим методом, так как это private. Что является обычной практикой в ​​такой ситуации?

Ответы [ 5 ]

3 голосов
/ 15 ноября 2010

Я бы сделал HTTPClient полем класса, который создается при построении (через интерфейс). Затем у вас есть возможность создать фиктивный HTTPClient, который может выдать исключение во время теста, если вы хотите, например:

public class Downloader {
  private IHTTPClient client;

  public Downloader(IHTTPClient client) {
    this.client = client;
  }

  public String download(String uri) { 
    this.initialiseHttpClient(); 
    client.setURI(uri); 
    return client.get(); 
  } 

  private HttpClient initialiseHttpClient() { 
    // + some config 
  } 
}

Затем вызовите конструктор с реальным HTTPClient в рабочем коде и Mock в тестовом коде. Возможно, вам потребуется создать оболочку для HTTPClient для реального кода.

1 голос
/ 15 ноября 2010

Если вы пытаетесь протестировать частные методы, я думаю, что-то не так.

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

Вам может необходимо заменить некоторые функциональные возможности в вашем классе для целей тестирования (например, заменить при разрыве соединения JDBC и т. Д.) В этом сценарии я бы исследовал насмешки и внедрение зависимостей.

0 голосов
/ 16 ноября 2010

Частные методы не должны проходить модульный тест.Вы должны только тестировать общедоступные методы.То, как публичный метод организован внутри, не имеет значения для модульного тестирования.Единица не равна методу.Это равносильно поведению, которое, возможно, использует более одного метода для выполнения своей работы.

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

0 голосов
/ 15 ноября 2010

Вы можете сделать getHttpClient () защищенным и сделать его подклассом в тесте, чтобы получить то, что вы хотите, чтобы в ваших тестах было что-то похожее на это:

public class TestableDownloader extends Downloader {

  protected HttpClient getHttpClient() {
    throw new Exception();
  }
}

Хотя это не идеально,вам лучше иметь другой дизайн, который не требует тестирования частных методов (возможно, с использованием внедрения зависимостей для предоставления фабрики или чего-то в этом роде).

0 голосов
/ 15 ноября 2010

Это звучит немного глупо, но я обычно делаю такие методы публичными и добавляю заметные javadocs, говорящие "этот метод открыт для общественности только для тестирования".

Вы также можете использовать доступ только к пакетам, имея xunit / mock и т. Д. В одном пакете.

Я предпочитаю использовать простые решения, подобные этим, а не более сложным и сложным для отладки методам, таким как внедрение кода в стиле AOP.

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