Подтвердить что ты не робот

Как я могу узнать, работает ли код внутри теста JUnit или нет?

В моем коде мне нужно сделать некоторые исправления только тогда, когда он запускается внутри теста JUnit. Как я могу узнать, работает ли код внутри теста JUnit или нет? Есть что-то вроде JUnit.isRunning() == true?

4b9b3361

Ответ 1

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

Если вы действительно хотите это сделать, вы можете посмотреть на stacktrace, но поскольку вы все равно меняете свою программу, вы можете просто ввести новое статическое логическое поле isUnitTesting в свой код и иметь JUnit установите для этого значение true. Держите его простым.

Ответ 2

Это может быть хорошей идеей, если вы хотите программно решить, какой "профиль" запускаться. Подумайте о Spring профилях для конфигурации. Внутри интеграционных тестов вы можете протестировать другую базу данных.

Здесь это проверенный код, который работает

public static boolean isJUnitTest() {
    StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
    List<StackTraceElement> list = Arrays.asList(stackTrace);
    for (StackTraceElement element : list) {
        if (element.getClassName().startsWith("org.junit.")) {
            return true;
        }           
    }
    return false;
}

Ответ 3

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

Например, в настоящее время я пишу тесты INTEGRATION (в отличие от Unit) для приложения, которое подключается к базе данных.

Эти приемочные тесты часто требуют полной повторной инициализации БД с конкретными тестовыми данными.

Очевидно, я не хочу, чтобы это было КОГДА-ЛИБО, КОГДА-ЛИБО, чтобы они выполнялись в реальной производственной БД, потому что это могло бы полностью стереть ценные производственные данные.

Самый простой способ гарантировать, что это никогда не произойдет, - сделать невозможным подключение кода к производственной БД при работе под JUnit. Это, в свою очередь, может быть выполнено, если, например, Factory, который создает соединение, может сказать, что он работает под JUnit и в этом случае вернет нулевое соединение, если только база данных, к которой мы пытаемся подключиться, имеет имя, которое Известно, что это тестовая база данных (например: "база данных тестов" ).

Ответ 4

Я могу найти оправдание для этого, то есть когда вы хотите предоставить код в производственном классе для тестирования. Это будет похоже на Java assert, который применяется только тогда, когда установлен флаг отладки.

Что-то вроде этого:

Object debugState() {
    // This is only meant to be called when testing
    if (!JUnit.isRunning()) {
        throw new IllegalStateException("Not in a test!");
    }
    // Now compute possibly costly debug information
    // not to be used in production
    Object state = ...
}

Ответ 5

Если вы делаете что-то по-другому, потому что вы делаете unit test, вы побеждаете цель unit test. Предполагается, что unit test выполняет точно так же, как производство (за исключением установки и удаления любых необходимых данных и таких, которые вам нужны.... но это включено в сам тест JUnit, а не ваш код).

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

Ответ 6

Как проверить, находится ли junit jar в пути к классам?

Ответ 7

При использовании Spring можно определить bean, который содержит это значение.

В контексте приложения:

@Bean
public boolean isRunningTests() {
    return false;
}

В контексте тестового приложения:

@Bean
public boolean isRunningTests() {
    return true;
}

Ввести значение в компонент Spring:

@Resource
private boolean isRunningTests;

private void someMethod() {
    if (isRunningTests()) {
        ....

Ответ 8

Чтобы различать тест и никакой тест, вы всегда можете определить специальное свойство или значение в application-test.properties.

Ответ 9

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

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

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

Ответ 10

Это сработало для меня:

private Boolean isRunningTest = null;

private boolean isRunningTest() {
    if (isRunningTest == null) {
        isRunningTest = true;
        try {
            Class.forName("org.junit.Test");
        } catch (ClassNotFoundException e) {
            isRunningTest = false;
        }
    }
    return isRunningTest;
}

Он может использоваться в тестах Maven, а также внутри Eclipse IDE, если в качестве зависимости с областью "test" включена junit, например:

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>${junit.version}</version>
    <scope>test</scope>
</dependency>

Ответ 11

Я согласен с предыдущими ответами, кажется, что плохая идея смешать тестовый код в производственном коде. Если вы не можете выполнить тесты, которые вы хотите использовать с JUnit и макетной картой, вы, вероятно, должны переосмыслить свой дизайн. Хорошие издевательские рамки: http://easymock.org/ http://mockito.org/

Ответ 12

это не связано с вопросом пользователя, но я уверен, что кто-то, кто туда попадет, может оказаться полезным.

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

например.

SRC/Основной/Java/ApplicationService.java

public class ApplicationService {
  private final Integer someInternalObject;

  public ApplicationService(String somePublicArgument) throws NumberFormatException {
    someInternalObject = Integer.valueOf(somePublicArgument, 16);
  }

  ApplicationService(Integer someInternalObject) {
     this.someInternalObject = someInternalObject;
  }
}

SRC/тест/ApplicationServiceTest.Java

public class ApplicationServiceTest {
  @Test
  public void testSomething() throws Exception {
    ApplicationService applicationService = new ApplicationService(0);
  }
}

выставить все тесты

не конечные классы

Расширить его в тестах и ​​предоставить публичный конструктор для локального или защищенного пакета.

заключительные классы

Сделайте общедоступный Factory Method в том же пакете (в тестах), который создаст его с помощью локального конструктора пакетов.