Как утверждать фактическое значение относительно 2 или более ожидаемых значений?

#java #unit-testing #junit #assert

#java #модульное тестирование #junit #утверждать

Вопрос:

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

Однако, поскольку порядок строк может измениться, написание просто инструкции Assert не сработает, поскольку иногда она пройдет тест, а иногда и не пройдет тест.

Итак, возможно ли написать тест, который будет утверждать фактическое строковое значение относительно 2 или более ожидаемых строковых значений и посмотреть, равно ли оно какому-либо из них?

Ответ №1:

Используя Hamcrest CoreMatcher (входит в JUnit 4.4 и более поздние версии) и assertThat() :

 assertThat(myString, anyOf(is("value1"), is("value2")));
  

Комментарии:

1. В конечном итоге мне удалось это исправить, но по какой-то причине для меня JUnit 4 не имеет метода ‘assertThat’ в CoreMatcher. В итоге я объединил основную библиотеку Hamcrest с библиотекой JUnit, чтобы заставить ее работать.

2. Не для меня… Я просто вижу assertTrue

3. @Andrey: ты уверен, что проверил org.junit.Assert и не junit.framework.Assert проверял? Более поздние существуют только для обратной совместимости с JUnit 3 и не поддерживают assertThat. In org.junit. ` Assert’ был введен в JUnit 4.4. Поэтому, если у вас более ранняя версия, он будет отсутствовать.

4. Вы пропустили одно ‘)’ в конце assertThat инструкции.

5. @JiaHaoXu: действительно, теперь исправлено. Обратите внимание, что вы можете самостоятельно отредактировать (или предложить отредактировать) ответ на подобные опечатки.

Ответ №2:

Я бы использовал AssertJ для этого:

 import static org.assertj.core.api.Assertions.*;

assertThat("hello").isIn("hello", "world");
  

Это более лаконично, и при сбое утверждения выдается описательное сообщение.

Ответ №3:

Я использую следующее, надеюсь, это поможет:

 String expectedTitles[] = {"Expected1","Expected2"};
List<String> expectedTitlesList = Arrays.asList(expectedTitles);

assertTrue(expectedTitlesList.contains((actualTitle)));
  

Комментарии:

1.для тех, кто использует junit Assert String expectedTitles[] = {"In-Progress","Completed"}; List<String> expectedTitlesList = Arrays.asList(expectedTitles); Assert.assertTrue(expectedTitlesList.contains((transferRequest.getRequestStatus())));

2. Для тех, кто вынужден использовать junit 3, это хорошее решение.

Ответ №4:

Для этого вы можете использовать Hamcrest:

 assertThat(testString, anyOf(
    containsString("My first string"), 
    containsString("My other string")));
  

(Я вижу, что Иоахим только что ответил очень похоже ( 1)… я добавлю это в качестве другого примера.)

Комментарии:

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

Ответ №5:

Я прочитал все ответы, но тот, который кажется мне наиболее компактным и выразительным, использует Hamcrest isOneOf , который уже включен в JUnit

 assertThat(result, isOneOf("value1", "value2"));
  

что выдает вам приятное сообщение об ошибке при сбое.

 java.lang.AssertionError: 
Expected: one of {"value1", "value2"}
     but: was "value"
    at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
[...]
  

Комментарии:

1. Какой оператор импорта у вас есть для isOneOf? Какая версия JUnit?

2. JUnit 4 с использованием Hamcrest 1.3 — hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest / …

3. Не рекомендуется: вместо этого используйте is(oneOf(…)).

Ответ №6:

Если вы используете junit, я бы просто сделал что-то вроде следующего:

 assertTrue(myString.equals("Value1") || myString.equals("Value"));
  

Комментарии:

1. Это плохая практика в тестировании. Хотя логически это пройдет и завершится сбоем, когда это предполагается, проблема в том, что в случае сбоя у вас не будет описательного сообщения об ошибке. вместо этого вы получите что-то вроде «ожидаемое значение true, но оказалось false», что ничего не говорит вам о проблеме. Но при использовании сопоставителей hamcrest или assertj при сбое вы получите что-то вроде этого: ожидалось одно из следующих значений: «Value1», «Value2», но было «XYZ»

Ответ №7:

Рассмотрите возможность написания пользовательского сопоставления hamcrest, возвращаемого методом, в данном случае containsOneOf , т.Е.:

 assertThat(myString, containsOneOf("value1", "value2"));
  

В соответствии с «шаблонами xUnit» вам следует избегать условной логики в вашем сопоставителе, цикла с оператором break должно быть достаточно.

Взгляните на шаблоны Hamcrest и xUnit для получения дополнительной информации.

Ответ №8:

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

    Set<String> expectedValues = ...
   String[] split = text.split("n");
   for(String str : split) {
      assert(expectedValues.contains(str));
   }
  

Если вы хотите проверить, присутствуют ли все ожидаемые значения, вы можете утверждать это expectedValue.remove(str) == true и утверждать после цикла, что набор пуст. Если некоторые строки могут встречаться несколько раз, вам придется использовать пакет вместо набора.

Ответ №9:

Самым простым / наиболее эффективным может быть

 assert str.equals(result1) || str.equals(result2);
  

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

Комментарии:

1. но в Android Studio я обнаружил, что утверждения не оцениваются в моих инструментальных тестах. Вместо этого мне нужно использовать assertTrue

2. @likejiujitsu вам нужно убедиться, что ea является опцией командной строки. assertEquals лучше всего подходит для тестирования, но используйте assert только в рабочей среде, поэтому его можно отключить.

3. assert.assertequals(expected, actual) не позволяет || operator

4. @Sanchit assetTrue делает.

5. Но при сбое это не покажет вам никакого значимого сообщения об ошибке. Использование hamcrest или assertj предоставляет вам что-то вроде «ожидаемые значения X, Y, но был Z»

Ответ №10:

Предполагая, что тестируемый метод возвращает массив, вы могли бы протестировать, используя arrayContainingInAnyOrder от Hamcrest . arrayContainingInAnyOrder от Hamcrest-а.

 assertThat(result, is(arrayContainingInAnyOrder("value1", "value2", "value")))
  

Примечание: использование is wrapper является чисто необязательным, используется только для улучшения читаемости.

Ответ №11:

Я думаю, вы можете просто использовать assertTrue:

assertTrue(testString.matches("string1|string2"));

Ответ №12:

Простое решение с использованием assertTrue.
Просто создайте List.of() ожидаемые значения и проверьте, содержит ли он ожидаемое значение.

 assertTrue(List.of("expected_1", "expected_2").contains("actual))
  

Ответ №13:

Если у вас нет или вы не можете использовать сторонние библиотеки, кроме junit core, вы можете использовать этот небольшой вспомогательный метод:

 public static void assertListContains(List<Object> expected, Object actual) {
    if (!expected.contains(actual)) {
        fail("Expected: "   expected   " Actual: "   actual);
    }
}
  

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

 org.opentest4j.AssertionFailedError: Expected: [1, 2] Actual: 3
  

Ответ №14:

Это старый пост, но я хотел получить простой ответ, не требующий добавления дополнительных библиотек. 🙂

Итак, я сделал :

 String e
e = "ear"
j = "jars"

assert (j == "jar" || e == "ear")
  

или, если вы хотите, чтобы они оба были истинными

 assert (j == "jar" amp;amp; e == "ear")
  

Ответ №15:

Мне кажется, это самое простое решение…

 assert obtainedValue in [acceptedValue1, acceptedValue2]