Могу ли я игнорировать аспект метода во время насмешки над ним с помощью Mockito?
У меня есть класс с несколькими методами, рекомендованными через аспект проверки входных данных (проверяет, являются ли все входные параметры ненулевыми / непустыми строками).
Я сталкиваюсь с проблемой при написании тестового примера для них и хочу проверить, действительно ли это плохая проблема дизайна.
Вот очень упрощенная версия моего класса:
public class A {
public String one(String word) {
// Some actions
String val = two(word2);
// Some more actions
}
protected String two(String word) {
// Some actions
}
}
Теперь при написании тестов для one()
Я использую Mockito и хочу издеваться над звонками two()
, Поэтому я использую:
@Spy
A a;
@Test
void test() {
doReturn("Bye").when(A).two(Mockito.anyString());
a.one("hello");
// Some validations
}
Этот тест не проходит как: doReturn()
Сбой строки с вводом, являющимся пустым для two()
,
Должен ли я не издеваться two()
или я могу как-то заставить эту работу работать?
Редактировать:
Добавив более конкретный пример, относящийся к двум методам, представленным в двух разных классах в соответствии с запросом:
Создайте страницу через веб-сервис. Это создает putRequest, выполняет его и возвращает ответ.
public class AUtility implements BaseUtility {
public Response create(Params params) {
try {
PutMethod putRequest = buildPUTRequest(params.getAttr1(), params.getAttr2());
return Utils.buildResponse(client.executeMethod(putRequest),
params.getAttr3(),
params.getAttr4());
} catch (Exception e) {
throw new AppException(e);
}
}
}
Запрос put помещает данные в файл и записывает их через HttpClient.
private PutMethod buildPUTRequest(final String url, final Object obj) throws IOException, JAXBException {
// Create a temp file to store the stream
File tempFile = File.createTempFile(APPLICATION_LABEL, XML_LABEL);
decoder.marshal(obj, tempFile);
// Build the put method
return putMethod;
}
XMLMarshaller
public interface XMLDecoder implement Decoder {
public void marshal(Object obj, File tempFile) throws IOException, JAXBException {
// Perform marshalling operations
}
}
Тест не пройден в строке 2 с нулевыми входами.
@Test
public void createPageParamsHttpException() throws HttpException, IOException, JAXBException {
expectedException.expect(AppException.class);
doNothing().when(decoder).marshal(Mockito.anyString(), Mockito.any(File.class));
doThrow(HttpException.class).when(client).executeMethod(Mockito.any(HttpMethod.class));
Params params = new Params(new Application(),
APPLICATION_URL_LABEL,
SITE_NAME_LABEL,
URL_WITHOUT_HTTP_N_HTML);
utility.createPage(params);
}
Есть идеи, как мне поступить так же?
1 ответ
Вы не хотите делать это.
Вы по своей сути меняете поведение класса. Если вы измените что two()
делает, откуда ты это знаешь one()
будет делать то, что должен делать в производстве?
Если вы действительно хотите сделать это, вы должны извлечь из two()
в другой класс верхнего уровня, а затем внедрить зависимость в A
, Тогда вы можете высмеивать эту зависимость, и вам не нужно беспокоиться о том, чтобы создать частичную насмешку для A
,
В том же духе, если вы должны держать two
в том же классе (потому что его поведение является частью той же ответственности, которая возложена на A
- см. Принцип единой ответственности - почему это public
?
Причина, по которой у вас возникли проблемы, заключается в том, что вы нарушаете SRP, см. Мое примечание выше. Вы сказали это:
Это создает putRequest, выполняет его и возвращает ответ.
Вы не должны пытаться проверить поведение всех этих трех вещей одновременно. В конечном счете, этот метод на самом деле ничего не делает. buildPUTRequest
метод делает, и не должен быть в классе с именем AUtility
должно быть в классе RequestFactory
, Затем вы хотели бы проверить Utils.buildResponse
метод, за исключением того, что не должно быть в классе с именем Utils
должно быть в классе с именем Responder
или что-то... и этот метод АБСОЛЮТНО не должно быть static
,
Работайте над тем, чтобы называть ваши классы лучшими вещами, и если вы не можете придумать хорошее имя, это означает, что класс, вероятно, делает слишком много и должен быть реорганизован. И метод, который оборачивает работу двумя другими методами, не нуждается в модульном тестировании. Интеграция проверена, возможно, но это уже другая история.