Утвердить, что опция имеет определенное значение

У меня есть метод Java, который возвращает Optional. Я хотел бы написать легко читаемый unit test для него, который утверждает, что

  • Возвращаемое необязательное значение имеет значение (т.е. необязательно не пусто) и что

  • возвращаемое значение равно ожидаемому значению.

Скажем, мой протестированный метод

Optional<String> testedMethod(){
  return Optional.of("actual value");
}

Ответ 1

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

@Test
public void testThatOptionalIsNotEmpty() {
    assertThat(testedMethod()).isNotEmpty();
}

@Test
public void testThatOptionalHasValue() {
    assertThat(testedMethod()).hasValue("hello");
}

Ответ 2

Существует несколько различных способов сделать это, в зависимости от вашего вкуса для ясности результатов теста и краткости написания теста. Для этого ответа я буду придерживаться "запаса" Java 8 и JUnit 4 без каких-либо дополнительных зависимостей.

Один из способов, предложенный в комментарии Ole V.V., - это просто написать

assertEquals("correct", opt.get());

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

Альтернативой является

assertTrue(opt.isPresent() && "correct".equals(opt.get()));

Это также работает в основном, но оно не сообщает фактическое значение, если существует несоответствие, которое может затруднить отладку.

Другая альтернатива -

assertEquals("correct", opt.orElseThrow(AssertionFailedError::new));

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

Еще одна альтернатива -

assertEquals("correct", opt.orElseThrow(() -> new AssertionFailedError("empty")));

но это начинает становиться многословным.

Вы можете разбить это на два утверждения,

assertTrue(opt.isPresent());
assertEquals("correct", opt.get());

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

Наконец, если вы захотите создать немного своей собственной инфраструктуры, вы можете создать подклассом под названием AssertionFailedError с соответствующим именем и использовать его следующим образом:

assertEquals("correct", opt.orElseThrow(UnexpectedEmptyOptional::new));

ОБНОВЛЕНИЕ В комментариях Оле В. В. предложил

assertEquals(Optional.of("correct"), opt);

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

Ответ 3

Я использую Hamcrest Необязательно для этого:

import static com.github.npathai.hamcrestopt.OptionalMatchers.hasValue;
import org.junit.Test;

public class MyUnitTests {

  @Test
  public void testThatOptionalHasValue(){
    String expectedValue = "actual value";
    assertThat(testedMethod(), hasValue(expectedValue));
  }
}

Вы можете добавить Hamcrest Необязательно для своих зависимостей, включив его в свой build.gradle:

dependencies {
  testCompile 'junit:junit:4.12'
  testCompile 'com.github.npathai:hamcrest-optional:1.0'
}

Ответ 4

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

@test
public void testThatOptionalHasValue() {
    String expectedValue = "actual value";
    String actualValue = Optional.ofNullable(testedMethod()).orElse("not " + expectedValue);
    assertEquals("The values are not the same", expectedValue, actualValue);
}

Это гарантирует, что если ваш метод возвращает значение null, результат не может быть таким же, как ожидаемое значение.

Ответ 5

Почему вы не используете isPresent() и get()?