Статьи

Улучшение assertEquals с помощью JUnit и Hamcrest

В моем сообщении в блоге все больше и больше принимается статический импорт в Java? Я обсуждал растущее использование статического импорта в Java, чтобы сделать код более беглым в определенных контекстах. На модульное тестирование в Java особенно повлиял статический импорт, и в этом сообщении в блоге я приведу один быстрый пример использования статического импорта для создания более быстрых модульных тестов, использующих JUnit и Hamcrest .

Следующий листинг кода — это простой класс IntegerArithmetic, в котором есть один метод, который необходимо протестировать модулем.

IntegerArithmetic.java 

package dustin.examples;

/**
 * Simple class supporting integer arithmetic.
 * 
 * @author Dustin
 */
public class IntegerArithmetic
{
   /**
    * Provide the product of the provided integers.
    * 
    * @param integers Integers to be multiplied together for a product.
    * @return Product of the provided integers.
    * @throws ArithmeticException Thrown in my product is too small or too large
    *     to be properly represented by a Java integer.
    */
   public int multipleIntegers(final int ... integers)
   {
      int returnInt = 1;
      for (final int integer : integers)
      {
         returnInt *= integer;
      }
      return returnInt;
   }
}

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

   /**
    * Test of multipleIntegers method, of class IntegerArithmetic, using standard
    * JUnit assertEquals.
    */
   @Test
   public void testMultipleIntegersWithDefaultJUnitAssertEquals()
   {
      final int[] integers = {2, 3, 4 , 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
      final int expectedResult = 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 *13 * 14 * 15;
      final int result = this.instance.multipleIntegers(integers);
      assertEquals(expectedResult, result);
   }

В довольно типичном примере модульного теста, показанном выше, assertEquals JUnit вызывается бегло из-за статического импорта org.junit.Assert. * (Не показано). Тем не менее, последние версии JUnit ( JUnit 4.4+ ) начали включать в себя средства сравнения ядра Hamcrest, и это позволяет проводить еще более быстрое тестирование, как показано в следующем фрагменте кода.

   /**
    * Test of multipleIntegers method, of class IntegerArithmetic, using core
    * Hamcrest matchers included with JUnit 4.x.
    */
   @Test
   public void testMultipleIntegersWithJUnitHamcrestIs()
   {
      final int[] integers = {2, 3, 4 , 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
      final int expectedResult = 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 *13 * 14 * 15;
      final int result = this.instance.multipleIntegers(integers);
      assertThat(result, is(expectedResult));
   }

В этом примере, JUnit assertThat (также доступный как часть статического импорта org.junit.Assert. * Начиная с JUnit 4.4 ) используется вместе с включенным основным соответствием Hamcrest is (). Это, конечно, дело вкуса, но я предпочитаю этот второй подход как более читаемый для меня. Утверждение, что что-то (результат) является чем-то другим (ожидаемым), кажется более читабельным и более свободным, чем старый подход. Иногда бывает сложно вспомнить, нужно ли сначала перечислять ожидаемый или фактический результат при использовании assertEquals и комбинации assertThat и is (), что делает немного меньше работы, когда я пишу и читаю тесты. Даже немного меньше работы, особенно если умножить на многочисленные тесты, приветствуется.