Как выполнить юнит-тест приватной функциональности - PullRequest
2 голосов
/ 15 марта 2012

У меня вопрос по модульному тестированию.

У меня есть функция, которая выполняет следующие действия:

void myFunction(List<MyClass> myList) {

// 1. Sort the list
// 2. Post Process the list

}

Теперь я хочу протестировать эту функцию.Но проблема в том, что я не должен проверять эти две вещи одновременно.Поэтому я подумываю извлечь часть «Постобработка списка» как отдельную функцию.

Но проблема в том, что задача «Постобработка списка» используется только myFunction, и я хочу сделать ее приватнойв класс.

Если я сделаю это приватным, я не смогу проверить это снаружи.

Каково общее правило такого сценария?Нужно ли менять частную функцию на публичную только для тестирования?

Или, если есть какие-то другие шаблоны, которые мне следует использовать?

Большое спасибо

Ответы [ 7 ]

3 голосов
/ 15 марта 2012

Метод тестирования должен быть только локальным для пакета.

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

2 голосов
/ 15 марта 2012

Как уже говорили другие, вам не нужно делать метод общедоступным, просто видим пакет.

Google Guava имеет аннотацию @VisibleForTesting, предназначенную для подобных ситуаций. Вы помещаете эту аннотацию в метод, просто чтобы документально подтвердить, что причина, по которой метод не является частным, предназначена только для тестирования. Аннотация ничего не делает, она просто предназначена для программистов как предупреждение, что они не должны вызывать ее извне класса. (Некоторый инструмент проверки статического кода может в принципе проверять, не вызваны ли методы с этой аннотацией откуда-либо, кроме как внутри класса или из тестового кода).

Конечно, некрасиво модифицировать свой код, чтобы сделать это только для тестирования. Если вы хотите избежать этого, вы можете сделать трюки с отражением, чтобы вызвать приватный метод:

public class Sandbox {
    public static void main(String[] args) throws Exception {
        Example e = new Example();

        Method m = Example.class.getDeclaredMethod("myFunction", List.class);
        m.setAccessible(true);
        m.invoke(e, Arrays.asList("one", "two", "three"));
    }
}

class Example {
    private void myFunction(List<String> data) {
        System.out.println("Hey, what are you doing! " + data);
    }
}
0 голосов
/ 16 марта 2012

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

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

Один из подходов с очень небольшими издержками - полагаться на базовое переопределение методов.Вместо этого вы можете сделать свои закрытые методы защищенными виртуальными и переопределить их в своем тесте: Вот также пример этого:
http://www.unit -testing.net / CurrentArticle / How-To-Remove-Data-Dependencies-In-Unit-Tests.html Примером является C #, но концепция применима ко всем объектно-ориентированным языкам

0 голосов
/ 15 марта 2012

Ниже вы можете рассмотреть вопрос о тестировании частного метода.

1.create public method written only for the purpose of testing. (or)

2.create nested class for testing (or)

3.use reflection to test it.

полезная ссылка , другая полезная ссылка из stackoverflow

0 голосов
/ 15 марта 2012

Это зависит.

Доза в подпрограмме содержит обычное поведение, которое вы должны извлечь?

Возьмите свою первую подпрограмму в качестве примера. Если вы не сортируете свой список по Comparator<T>, вам следует реорганизовать его, а затем протестировать этот класс Comprartor<T> вместо вашего частного метода. Если Post process на самом деле является каким-то алгоритмом или общей бизнес-логикой, вы можете реорганизовать его, используя шаблон стратегии, а затем протестировать класс, который вы только что извлекли.

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

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

check Плохие запахи в коде: длинный метод для длинного метода-рефактора, Method Object - хорошая стратегия для подобных вещей.

Хорошо, я просто хочу их проверить.

Тогда вы можете протестировать с помощью API отражения Java , и я полагаю, что есть некоторые насмешливые рамки, такие как PowerMock , которые также могут вам помочь.

0 голосов
/ 15 марта 2012

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

0 голосов
/ 15 марта 2012

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

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