Задержка выброшенного исключения для добавления вместо него мягкого утверждения

Предположим, у меня есть метод для тестирования, который

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

Некоторые побочные эффекты можно наблюдать (и тестировать) даже при выдаче исключения. Мой пример тестового кода приведен ниже:

final SoftAssertions softly = new SoftAssertions();

try {
    /*
     * May throw an exception
     */ 
    doSmth();
} catch (final IOException ioe) {
    /*
     * How do I add a soft assertion wrapping an exception?
     */ 
}

/*
 * Testing for side effects.
 */
softly.assertThat(...).as("%s exit code", ...).isEqualTo(0);
softly.assertThat(...).as("the number of downloaded files").isEqualTo(3);
softly.assertThat(...).as("this should be true").isTrue();
softly.assertThat(...).as("and this should be true, too").isTrue();

softly.assertAll();

Вопрос 1

Каков наилучший способ создать еще одно мягкое утверждение из выброшенного исключения? С необработанным API TestNG я мог просто написать

softly.fail(ioe.toString(), ioe);

но AssertJ похоже не дает ничего подобного. Пока что мой лучший вариант — добавить что-то вроде этого в блок catch:

softly.assertThat(true).as(ioe.toString()).isFalse();

Есть ли лучшие альтернативы?

вопрос 2

Как сделать так, чтобы исключения, выдаваемые моим тестируемым кодом, отображались как причина (или подавленные исключения) результирующего AssertionError? В настоящее время я делаю следующее:

Throwable failure = null;
try {
    doSmth();
} catch (final IOException ioe) {
    failure = ioe;
}

try {
    softly.assertAll();
} catch (final AssertionError ae) {
    if (failure != null) {
        if (ae.getCause() == null) {
            ae.initCause(failure);
        } else {
            ae.addSuppressed(failure);
        }
    }
    throw ae;
}

- но более элегантная версия высоко ценится.


person Bass    schedule 01.03.2018    source источник


Ответы (2)


для вопроса 1 предложение Xaero работает нормально.

Однако для решения обоих вопросов попробуйте использовать catchThrowable в сочетании с fail(String failureMessage, Throwable realCause) (или один для мягких утверждений).

Если вы поймали исключение, отличное от null (что означает, что тестируемый код вызвал исключение), вы можете использовать fail для создания AssertionError с пользовательским сообщением об ошибке и передать пойманное исключение в качестве причины AssertionError.

Код будет выглядеть так:

Throwable thrown = catchThrowable(() -> { doSmth(); });

if (thrown != null) {
  softly.fail("boom!", thrown);
} else {
  softly.assertThat(...).as("%s exit code", ...).isZero();
  softly.assertThat(...).as("the number of downloaded files").isEqualTo(3);
  softly.assertThat(...).as("this should be true").isTrue();
  softly.assertThat(...).as("and this should be true, too").isTrue();
}

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

В любом случае, надеюсь, что это поможет!

PS: обратите внимание, что вы можете использовать isZero() вместо isEqualTo(0)

person Joel Costigliola    schedule 04.03.2018
comment
Я разделяю вашу озабоченность по поводу сценариев двойного тестирования. Вот почему я не мог дать ответ, который меня устраивал для второго сценария, поскольку существует слишком большое отклонение между тем, что на самом деле тестируется, и обсуждаемым вопросом (если это имеет смысл). - person Xaero Degreaz; 05.03.2018

Вопрос 1. Вы можете использовать assertThatThrownBy для этого:

softly.assertThatThrownBy(() -> doSmth())
    .isInstanceOf(Exception.class)
    .hasMessage("My Message");
person Xaero Degreaz    schedule 01.03.2018
comment
Спасибо. Рег. 1-й вопрос, я хочу, чтобы мое мягкое утверждение в конечном итоге потерпело неудачу, если было выбрано исключение, поэтому softly.assertThatCode(() -> doSmth()).doesNotThrowAnyException() более подходит. Рег. 2-й вопрос - я хочу манипулировать не причиной первоначального отказа, а причиной окончательного AssertionError, выброшенного из softly.assertAll();. - person Bass; 01.03.2018
comment
Извините, у меня нет ответа на этот вопрос, но кажется, что, поскольку вы задаете два отдельных вопроса, они также заслуживают двух отдельных вопросов SO. Это может лучше послужить вашей цели, поскольку заголовок вашего второго вопроса может быть более показательным для вашей проблемы. - person Xaero Degreaz; 01.03.2018
comment
Может быть, вы можете попробовать сделать свой экземпляр мягких утверждений объектом-шпионом, тогда вы сможете манипулировать возвращаемыми значениями так же, как у макета. - person Xaero Degreaz; 23.03.2018