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

execute

show VARIABLES like "%char%”;

find character-set-server, если не utf8mb4.

установить его в my.cnf, например

vim /etc/my.cnf

добавить одну строку

character-set-server = utf8mb4

при последнем перезапуске mysql

2527
задан 18 revs, 9 users 48% 14 December 2017 в 17:13
поделиться

23 ответа

Обновление:

приблизительно 10 лет спустя, возможно, лучший способ протестировать закрытый метод или любого недоступного участника, через [1 127] @Jailbreak от Коллектор платформа.

@Jailbreak Foo foo = new Foo();
// Direct, *type-safe* access to *all* foo's members
foo.privateMethod(x, y, z);
foo.privateField = value;

Этот путь Ваш код остается безопасным с точки зрения типов и читаемым. Никакие компромиссы дизайна, никакие методы переэкспонирования и поля ради тестов.

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

Внутренне мы используем помощников, чтобы получить/установить private и private static переменные, а также вызвать private и private static методы. Следующие шаблоны позволят Вам сделать в значительной степени что-либо связанное с закрытыми методами и полями. Конечно, Вы не можете измениться private static final переменные посредством отражения.

Method method = TargetClass.getDeclaredMethod(methodName, argClasses);
method.setAccessible(true);
return method.invoke(targetObject, argObjects);

И для полей:

Field field = TargetClass.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object, value);
<час>

Примечания:
1. TargetClass.getDeclaredMethod(methodName, argClasses) позволяет Вам изучить private методы. То же самое запрашивает getDeclaredField.
2. Эти setAccessible(true) требуется, чтобы играть вокруг с рядовыми.

1550
ответ дан 10 revs, 6 users 45% 14 December 2017 в 17:13
поделиться

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

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

, Это не верно. Вы несомненно можете, как упомянуто в ответ Cem Catikkas .

6
ответ дан 7 revs, 4 users 45% 14 December 2017 в 17:13
поделиться

Судя Cem Catikkas решение с помощью отражения для Java, я должен был бы сказать его, было более изящное решение, чем я описал здесь. Однако, если Вы ищете альтернативу использованию отражения и имеете доступ к источнику, Вы тестируете, это все еще будет опцией.

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

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

Преимущества:

  • Может протестировать к более прекрасной гранулярности

Недостатки:

  • Тестовый код должен находиться в том же файле как исходный код, который может быть более трудно поддержать
  • Так же с .class выходными файлами, они должны остаться в том же пакете, как объявлено в исходном коде

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

Вот замысловатый пример того, как это работало бы:

// Import statements and package declarations

public class ClassToTest
{
    private int decrement(int toDecrement) {
        toDecrement--;
        return toDecrement;
    }

    // Constructor and the rest of the class

    public static class StaticInnerTest extends TestCase
    {
        public StaticInnerTest(){
            super();
        }

        public void testDecrement(){
            int number = 10;
            ClassToTest toTest= new ClassToTest();
            int decremented = toTest.decrement(number);
            assertEquals(9, decremented);
        }

        public static void main(String[] args) {
            junit.textui.TestRunner.run(StaticInnerTest.class);
        }
    }
}

внутренний класс был бы скомпилирован в ClassToTest$StaticInnerTest.

См. также: Подсказка по Java 106: Статические внутренние классы для забавы и прибыли

27
ответ дан 5 revs, 3 users 73% 14 December 2017 в 17:13
поделиться

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

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

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

22
ответ дан 2 revs, 2 users 80% 14 December 2017 в 17:13
поделиться

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

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

11
ответ дан Darren Greaves 14 December 2017 в 17:13
поделиться

Если Вы используете JUnit, взглянули на junit-дополнения . Это имеет способность проигнорировать модель обеспечения безопасности Java и закрытые методы доступа и атрибуты.

14
ответ дан 3 revs, 3 users 67% 14 December 2017 в 17:13
поделиться

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

113
ответ дан 3 revs, 2 users 60% 14 December 2017 в 17:13
поделиться

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

14
ответ дан bmurphy1976 14 December 2017 в 17:13
поделиться

Если Вы хотите протестировать закрытые методы унаследованного приложения, где Вы не можете изменить код, одна опция для Java jMockit, который позволит Вам создавать насмешки к объекту, даже когда они являются частными к классу.

16
ответ дан 3 revs, 3 users 67% 14 December 2017 в 17:13
поделиться

Закрытые методы называет открытый метод, таким образом, исходные данные к Вашим открытым методам должны также протестировать закрытые методы, которые называют те открытые методы. Когда открытый метод перестал работать, тогда это могло быть отказом в закрытом методе.

55
ответ дан Thomas Owens 14 December 2017 в 17:13
поделиться

От этой статьи: Закрытые методы Тестирования с JUnit и (Bill Venners) SuiteRunner , у Вас в основном есть 4 опции:

  • не тестируют закрытые методы.
  • Предоставляют доступ пакета методов.
  • Использование вложенный тестовый класс.
  • отражение Использования.
201
ответ дан 3 revs, 3 users 70% 14 December 2017 в 17:13
поделиться

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

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

новый класс представляет эти методы как 'общественность', таким образом, они доступны для поблочного тестирования. Новые и старые классы теперь оба более просты, чем исходный класс, который является большим для меня (я должен сохранить вещи простыми, или я заблудился!).

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

296
ответ дан 3 revs, 2 users 81% 14 December 2017 в 17:13
поделиться

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

  1. закрытый метод является мертвым кодом
  2. существует запах дизайна около класса, который Вы тестируете
  3. метод, который Вы пытаетесь протестировать, не должен быть частный
567
ответ дан Trumpi 14 December 2017 в 17:13
поделиться

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

Так не тестируют закрытые методы.

17
ответ дан 2 revs, 2 users 60% 14 December 2017 в 17:13
поделиться

Во-первых, я выведу этот вопрос: Почему Вашим членам парламента, не занимающим официального поста нужно изолированное тестирование? Они то, что комплекс, обеспечивая такие сложные поведения для требования тестирования кроме общедоступной поверхности? Это - поблочное тестирование, не тестирование 'строки кода'. Не потейте маленький материал.

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

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

8
ответ дан 2 revs, 2 users 67% 9 September 2019 в 18:20
поделиться

Как другие сказали... не тестируют закрытые методы непосредственно. Вот несколько мыслей:

  1. Сохраняют все методы маленькими и сфокусированными (легкий протестировать, легкий найти что не так)
  2. инструменты покрытия кода Использования. Мне нравится Cobertura (о, счастливый день, похож на новую версию, отсутствует!)

Выполнение покрытие кода на модульных тестах. Если Вы видите, что методы не полностью тестируются, добавляют к тестам для подъема покрытия. Стремитесь к 100%-му покрытию кода, но поймите, что Вы, вероятно, не получите его.

24
ответ дан 5 revs, 5 users 64% 10 September 2019 в 04:20
поделиться
  • 1
    Всегда стоящий упоминания очевидное. Иногда я нахожу, что битовая маска или взломы без веток, которые, как предполагается, быстрее, действительно медленнее. Все зависит от процессора и компилятора. – Paul Chernoch 22 October 2013 в 02:00

В C# Вы, возможно, использовали System.Reflection, хотя в Java я не знаю. Хотя я чувствую желание ответить на это так или иначе с тех пор, если Вы "чувствуете, что Вы нуждаться к закрытым методам модульного теста" в моем предположении - то, что существует что-то еще, что является неправильным...

я серьезно рассмотрел бы рассмотрение моей архитектуры снова новыми глазами...

2
ответ дан 2 revs, 2 users 50% 10 September 2019 в 04:20
поделиться

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

Эти setAccessible(true) вызов делает это.

единственное ограничение - то, что ClassLoder может запретить Вам от выполнения этого.

См. Ниспровергающая Защита Доступа Java для Поблочного тестирования (Ross Burton) для способа сделать это в Java.

3
ответ дан 6 revs, 5 users 45% 10 September 2019 в 04:20
поделиться
  • 1
    Когда это на самом деле установить? и это сохранится? Так 3 дня с этого времени, это все еще имело бы дату от 3 дня назад? – chovy 1 October 2012 в 09:21

Я использовал отражение , чтобы сделать это для Java в прошлом, и, на мой взгляд, это была большая ошибка.

Строго говоря, вы не должны не писать модульные тесты, которые напрямую тестируют частные методы. Что вы должны тестировать, так это открытый контракт, который класс имеет с другими объектами; вы никогда не должны напрямую тестировать внутреннее устройство объекта. Если другой разработчик хочет внести небольшое внутреннее изменение в класс, которое не влияет на публичный контракт классов, он / она затем должен изменить ваш тест на основе отражения, чтобы убедиться, что он работает. Если вы делаете это неоднократно на протяжении проекта, модульные тесты перестанут быть полезным измерением состояния кода и начнут становиться помехой для разработки и раздражением для команды разработчиков.

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

270
ответ дан 22 November 2019 в 19:51
поделиться

Только два примера того, где я хотел бы протестировать приватный метод:

  1. Процедуры дешифрования - я не хотел бы делать их видимыми для всех желающих только ради ради тестирования, иначе любой может использовать их для расшифровки. Но они присущи коду, сложны, и должны всегда работать (очевидным исключением является reflection, который может быть использован для просмотра даже приватных методов в большинстве случаев, если SecurityManager не настроен для предотвращения этого).
  2. Создание SDK для сообщества потребления. Здесь public приобретает совершенно другое значение, поскольку это это код, который может увидеть весь мир (а не только внутри моего приложения). Я помещаю код в приватные методы, если я не хочу, чтобы пользователи SDK видели его - я не считаю это запахом кода, просто как работает программирование SDK. Но, конечно конечно, мне все равно нужно тестировать мои частные методы, и именно в них функциональность моего SDK живет.

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

Так что мой компромисс включает в себя усложнение JUnits с отражением, а не компрометацию безопасности и SDK.

64
ответ дан 22 November 2019 в 19:51
поделиться

Для C++ (начиная с C++ 11) добавление тестового класса как друг работает отлично и не повреждает производственную инкапсуляцию.

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

// prod.h: some production code header

// forward declaration is enough
// we should not include testing headers into production code
class FooTest;

class Foo
{
  // that does not affect Foo's functionality
  // but now we have access to Foo's members from FooTest
  friend FooTest;
public:
  Foo();
private:
  bool veryComplicatedPrivateFuncThatReallyRequiresTesting();
}
// test.cpp: some test
#include <prod.h>

class FooTest
{
public:
  void complicatedFisture() {
    Foo foo;
    ASSERT_TRUE(foo.veryComplicatedPrivateFuncThatReallyRequiresTesting());
  }
}

int main(int /*argc*/, char* argv[])
{
  FooTest test;
  test.complicatedFixture();  // and it really works!
}
0
ответ дан 22 November 2019 в 19:51
поделиться

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

import com.google.common.base.Preconditions;

import org.springframework.test.util.ReflectionTestUtils;

/**
 * <p>
 * Invoker
 * </p>
 *
 * @author
 * @created Oct-10-2019
 */
public class Invoker {
    private Object target;
    private String methodName;
    private Object[] arguments;

    public <T> T invoke() {
        try {
            Preconditions.checkNotNull(target, "Target cannot be empty");
            Preconditions.checkNotNull(methodName, "MethodName cannot be empty");
            if (null == arguments) {
                return ReflectionTestUtils.invokeMethod(target, methodName);
            } else {
                return ReflectionTestUtils.invokeMethod(target, methodName, arguments);
            }
        } catch (Exception e) {
           throw e;
        }
    }

    public Invoker withTarget(Object target) {
        this.target = target;
        return this;
    }

    public Invoker withMethod(String methodName) {
        this.methodName = methodName;
        return this;
    }

    public Invoker withArguments(Object... args) {
        this.arguments = args;
        return this;
    }

}

Object privateMethodResponse = new Invoker()
  .withTarget(targetObject)
  .withMethod(PRIVATE_METHOD_NAME_TO_INVOKE)
  .withArguments(arg1, arg2, arg3)
  .invoke();
Assert.assertNotNutll(privateMethodResponse)
0
ответ дан 22 November 2019 в 19:51
поделиться

Что, если ваши тестовые классы находятся в том же пакете, что и класс, который должен быть протестирован?

Но в другом каталоге конечно, src & классы для вашего исходного кода, test / src и test / classes для ваших тестовых классов. И пусть классы и test / classes будут в вашем пути к классам.

test / src и test / classes для ваших тестовых классов. И пусть классы и test / classes будут в вашем пути к классам.

test / src и test / classes для ваших тестовых классов. И пусть классы и test / classes будут в вашем пути к классам.

2
ответ дан 22 November 2019 в 19:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: