Могу ли я игнорировать аспект метода во время насмешки над ним с помощью 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,

Работайте над тем, чтобы называть ваши классы лучшими вещами, и если вы не можете придумать хорошее имя, это означает, что класс, вероятно, делает слишком много и должен быть реорганизован. И метод, который оборачивает работу двумя другими методами, не нуждается в модульном тестировании. Интеграция проверена, возможно, но это уже другая история.

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