Модульное тестирование шифрования / дешифрования

#java #unit-testing #junit #bytearray #junit4

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

Вопрос:

Я реализовал очень простой класс с именем Enigma , который имеет симметричный ключ и два метода: byte[] encryptString(String strToEncrypt) и String decryptBytes(byte[] arrayToDecrypt) .

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

Однако я не знаю, как получить представление вывода массива байтов byte[] encryptString(String strToEncrypt) , чтобы я мог жестко закодировать его в тестовом классе.

Есть идеи?

Ответ №1:

Несколько замечаний о том, как это проверить (предупреждение о личном мнении :-))

  • Если вы пишете модульные тесты, избегайте чтения ожидаемых результатов из файлов, поскольку это замедляет тест (модульные тесты должны быть очень быстрыми), а также создает другую вещь, не имеющую отношения к вашему коду, которая может пойти не так (т. Е. Файл может быть удален и т.д.)
  • Не используйте тот же метод, который вы тестируете, для получения ожидаемых результатов, с помощью которых вы проверяете метод. Это бессмысленно, если вы пытаетесь проверить алгоритм, и может увековечить ошибки в алгоритме
  • Учтите тот факт, что наименьшая единица работы в Java — это класс, а не метод (забудьте на секунду о лямбда-выражениях Java 8, вы не будете писать модульные тесты для них напрямую), поэтому вам следует попытаться протестировать класс, а не методы

Мой последний пункт подводит меня (наконец?) к рекомендации. Подумайте о том, за что отвечает класс (надеюсь, единственная ответственность, см. SRP). В этом случае я считаю, что ответственность вашего класса заключается в двустороннем шифровании строк.
Поэтому я бы написал следующие тесты:

 @Test
public void testThatEncryptingStringResultsInExpectedBytes() {
    byte[] encryption = enigma.encryptString(TEST_STRING);

    assertArrayEquals(EXPECTED_ENCRYPTION, encryption);
}

@Test
public void testThatDecryptinEncryptionResultsInOriginalString() {
    String decryption = enigma.decryptBytes(TEST_ENCRYPTION);

    assertEquals(EXPECTED_ORIGINAL_STRING, decryption);
}

@Test
public void testThatDecriptionReversesEncryption() {
    String decryption = enigma.decryptBytes(enigma.encryptString(TEST_STRING));

    assertEquals(TEST_STRING, decryption);
}

@Test
public void testThatEncryptionReversesDecryption() {
    byte[] encryption = enigma.encriptString(enigma.decryptBytes(TEST_ENCRYPTION));

    assertEquals(TEST_ENCRYPTION, encryption);
}
 

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

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

1. Спасибо, это то, что я, наконец, сделал (используя онлайн-инструмент шифрования для получения результатов в шестнадцатеричном формате).

2. комментарий и вопрос: не уверен, что обратные тесты могут быть применены к каждому шифрованию (думаю, это имеет смысл только для симметричных алгоритмов). Я согласен, что чтение файлов замедляет модульные тесты, которые должны быть молниеносными.. Как бы вы обошли это при тестировании генерации xml с помощью JUnit? какие-либо советы или примеры по этому поводу?

3. Прежде всего, позвольте мне просто подчеркнуть, что более серьезной проблемой, чем медлительность (хотя и БОЛЬШАЯ проблема) при чтении файлов во время модульного тестирования, является несогласованность, потеря повторяемости и потеря изоляции. Чтение файлов зависит от ввода-вывода, что означает, что может произойти сбой, каждый запуск может занимать разное время и т. Д. Выполнение операций ввода-вывода во время теста не позволяет ему быть модульным тестом. Что касается генерации XML, определите свой генератор для получения выходного файла записи / потока в качестве параметра конструктора / метода или путем инъекции. Модульный тест предоставит макет выходного буфера.

4. Извините за короткий ответ, количество символов в комментарии ограничено. Если вам нужен лучший ответ, пожалуйста, отправьте вопрос, и я отвечу на него должным образом.

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