JMockit - проверить частный метод

Метод ниже имеет 3 возможных пути: 1. True, 2. False, 3. Exception.

Чтобы проверить это, мне нужно смоделировать частный getWootsWithAvailableProducts для путей True и Exception. Однако коллективный разум, кажется, говорит о том, что вы не должны издеваться над частными методами. Как еще я могу проверить эти пути, если я не издеваюсь над частным методом и не слежу за ним для проверки. Если это все правда, то почему так сложно издеваться над приватными методами. Если это не так, что я упускаю?

Тестируется:

  public List<Woot> findAllWoots(final boolean isBuy) throws Exception {

    final List<Woot> allWoots = wootService.findAllWoots();

    return isBuy ? getWootsWithAvailableProducts(allWoots) : allWoots;
  }

Дополнительные сведения:

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

private List<Woot> getWootsWithAvailableProducts(List<Woot> allWoots)
    throws ServiceException {

    final String stringOfWootIds = buildStringOfCommaSeparatedIDs(allWoots);
    final List<Count> categoryIDs = wootSearchService
        .getWootIDsOfAvailableProducts(stringOfWootIds);

    return filterOnlyWootsWithAvailProducts(allCategories, categoryIDs);// also private.
}

person nullsteph    schedule 16.03.2018    source источник
comment
Есть ли какие-либо последствия от звонка getWootsWithAvailableProducts?   -  person Nkosi    schedule 16.03.2018
comment
Да, он вызывает службу, которая делает сетевой запрос.   -  person nullsteph    schedule 16.03.2018
comment
это внешняя зависимость, которую следует абстрагировать в отдельную задачу, поскольку она сильно связывает ваш код и затрудняет изолированное тестирование.   -  person Nkosi    schedule 16.03.2018
comment
Это означает либо следующее: 1. Ваша зависимость от сетевой службы скрыта и не может быть сымитирована, и ваш класс без необходимости связан с ней; 2. Ваш класс делает слишком много; 3. (весьма вероятно) Ваше представление о тестировании неверно, и ваши тесты будут очень тесно связаны с тестируемыми классами. Расширьте область тестирования и напишите тесты как спецификацию модуля, а не тест для каждой ветки if/else.   -  person Zdeněk Jelínek    schedule 16.03.2018
comment
В этом методе только два пути, а не три. Коллективный разум прав в том, что нельзя издеваться над частными методами, поскольку они являются просто деталями реализации. Важная вещь, которую нужно понимать об автоматических тестах разработчиков, заключается в том, что они должны проверять значительную функциональность и ничего более; хороший тест заботится только о проверке бизнес-функции какой-либо части ТРИ, он не заботится о фрагментах кода. А мокирование лучше вообще не использовать, если это возможно. Используйте его только в случае крайней необходимости.   -  person Rogério    schedule 17.03.2018


Ответы (2)


Из комментариев было указано, что getWootsWithAvailableProducts

вызывает службу, которая делает сетевой запрос

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

public interface WootProductsService {
    List<Woot> getWootsWithAvailableProducts(List<Woot> woots);
}

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

WootProductsService wootProductService; //Injected

public List<Woot> findAllWoots(final boolean isBuy) throws Exception {

    final List<Woot> allWoots = wootService.findAllWoots();

    return isBuy ? wootProductService.getWootsWithAvailableProducts(allWoots) : allWoots;
}

Теперь у вас есть контроль над всеми зависимостями и вы можете манипулировать ими по своему усмотрению при тестировании для всех сценариев.

Обратите внимание на проблемы ваших методов и, соответственно, классов, так как они укажут, не слишком ли много делает ваш класс.

Когда вы сталкиваетесь с проблемой при тестировании своего кода, воспринимайте это как признак того, что что-то не так с его дизайном. Просмотрите причину проблемы и подумайте, какие рефакторинги необходимо применить, чтобы сделать код более НАДЕЖНЫМ.

person Nkosi    schedule 16.03.2018
comment
Я обновил вопрос, добавив более подробную информацию, о которой, как я полагаю, вы говорите. Например, класс обслуживания имитируется с помощью @Injected и его общедоступности в тестируемом классе. Тем не менее, я даже не вижу закрытый метод в тестовом коде, и делать его общедоступным кажется неправильным, хотя я полагаю, что это может быть ответом. - person nullsteph; 16.03.2018
comment
@nullsteph Вы слишком много внимания уделяете тестированию частного метода. Как уже упоминалось, сосредоточьтесь на общедоступном методе и проверьте, что он ведет себя должным образом. Моделируйте любые зависимости, которые позволят тестируемому методу выполняться до конца с учетом возможных сценариев. - person Nkosi; 16.03.2018
comment
Спасибо за советы. Я не хотел тестировать этот метод в этом тесте, просто подтвердите, что он был вызван. Этот тест теперь просто проверяет два возвращаемых типа; Список и исключение - person nullsteph; 17.03.2018

Вы можете написать тесты для доступных методов, из которых вызывается этот закрытый метод, а затем протестировать все возможные результаты.

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

Итак, в основном вы будете тестировать возможные сценарии, подобные этому:

Публичная функция, когда возвращается частная функция

  1. истинный
  2. ложный
  3. исключение

Надеюсь, это поможет.

person Aman Chhabra    schedule 16.03.2018