Как мне проверить приватную функцию или класс, который имеет закрытые методы, поля или внутренние классы? - PullRequest
2484 голосов
/ 29 августа 2008

Как мне выполнить модульное тестирование (используя xUnit) класс, который имеет внутренние закрытые методы, поля или вложенные классы? Или функция, которая становится закрытой, имея внутреннюю связь (static в C / C ++) или находится в закрытом ( анонимном ) пространстве имен?

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

Ответы [ 48 ]

1 голос
/ 28 июня 2018

Моя команда и я используем Typemock, у которого есть API, который позволяет подделывать непубличные методы. Недавно они добавили возможность подделывать невидимые типы и использовать XUnit.

1 голос
/ 08 сентября 2017

Вы можете использовать PowerMockito для установки значений возврата для приватных полей и приватных методов, которые вызываются / используются в приватном методе, который вы хотите протестировать:

Например. Установка возвращаемого значения для частного метода:

MyClient classUnderTest = PowerMockito.spy(new MyClient());

//Set expected return value
PowerMockito.doReturn(20).when(classUnderTest, "myPrivateMethod", anyString(), anyInt());
//This is very important otherwise it will not work
classUnderTest.myPrivateMethod(); 

//Setting private field value as someValue:
Whitebox.setInternalState(classUnderTest, "privateField", someValue);

Затем, наконец, вы можете проверить, что тестируемый вами закрытый метод возвращает правильное значение на основе указанных значений:

String msg = Whitebox.invokeMethod(obj, "privateMethodToBeTested", "param1");
Assert.assertEquals(privateMsg, msg);

или

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

//To get value of private field
MyClass obj = Whitebox.getInternalState(classUnderTest, "foo");
assertThat(obj, is(notNull(MyClass.class))); // or test value
1 голос
/ 04 марта 2013

JML имеет синтаксис аннотации для spec_public комментариев, который позволяет вам указывать метод как public во время тестов:

private /*@ spec_public @*/ int methodName(){
...
}

Этот синтаксис обсуждается на http://www.eecs.ucf.edu/~leavens/JML/jmlrefman/jmlrefman_2.html#SEC12. Также существует программа, которая переводит спецификации JML в тесты JUnit. Я не уверен, насколько хорошо это работает или каковы его возможности, но в этом нет необходимости, поскольку JML сам по себе является жизнеспособной средой тестирования.

0 голосов
/ 12 мая 2019

PowerMock.Whitebox - лучший вариант, который я видел, но когда я читаю его исходный код, он читает приватные поля с отражением, поэтому я думаю, что у меня есть ответ:

  • тестирование частных внутренних состояний (полей) с PowerMock или просто отражение без дополнительных затрат на введение другой независимости
  • для частных методов: на самом деле, положительный ответ на этот вопрос и огромное количество комментариев и ответов показывает, что это очень противоречивая и противоречивая тема , где не может быть дан конкретный ответ для любых обстоятельств . Я понимаю, что только контракт должен быть проверен, но у нас также есть покрытие, чтобы рассмотреть. На самом деле, Я сомневаюсь, что только контракты на тестирование на 100% сделают класс невосприимчивым к ошибкам . Частные методы - это те, которые обрабатывают данные в классе, в котором они определены, и, следовательно, не интересуют другие классы, поэтому мы не можем просто предоставить их для тестирования. Я постараюсь не проверять их , но когда вам нужно, , просто сделайте это и забудьте все ответы здесь . Вы знаете свою ситуацию и ограничения лучше, чем кто-либо другой в Интернете. Когда у вас есть контроль над вашим кодом, используйте это. С учетом, но без обдумывания.
0 голосов
/ 09 апреля 2019

Существует другой подход для проверки ваших частных методов. Если вы «включаете утверждение» в конфигурациях запуска, то вы можете тестировать свой метод внутри самого метода. Например;

assert ("Ercan".equals(person1.name));
assert (Person.count == 2);
0 голосов
/ 13 декабря 2018

Вы можете создать специальный публичный метод для прокси приватного метода для тестирования. Аннотация @TestOnly доступна из коробки при использовании IntelliJ. Недостатком является то, что если кто-то хочет использовать приватный метод в публичном контексте, он может это сделать. Но он будет предупрежден аннотацией и названием метода. На IntelliJ при этом появится предупреждение.

import org.jetbrains.annotations.TestOnly

class MyClass {

    private void aPrivateMethod() {}

    @TestOnly
    public void aPrivateMethodForTest() {
        aPrivateMethod()
    }
}
0 голосов
/ 28 апреля 2011

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

Я минимизирую необходимость в этом, и всегда документирую точные причины, чтобы избежать путаницы.

0 голосов
/ 03 января 2012

Groovy имеет ошибку / функцию , с помощью которой вы можете вызывать приватные методы, как если бы они были публичными. Так что если вы можете использовать Groovy в своем проекте, это вариант, который вы можете использовать вместо размышлений. Проверьте эту страницу для примера.

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