Использование assertArrayEquals() с подстановочными знаками?

#java #junit #bytearray #mockito #hamcrest

#java #юнит #bytearray #mockito #хэмкрест

Вопрос:

Я хочу протестировать код, который создает байтовые массивы, используемые для отправки в виде UDP-пакетов.

Хотя я не могу воспроизвести каждый байт в своем тесте (например, случайные байты, временные метки), я хотел бы протестировать байты, которые я могу предопределить.

Возможно ли что-то вроде следующего, используя JUnit 4.8 (и Mockito 1.8)?

 Packet packet = new RandomPacket();

byte[] bytes = new byte[] {
    0x00, 0x02, 0x05, 0x00, anyByte(), anyByte(), anyByte(), anyByte(), 0x00
};

assertArrayEquals(packet.getBytes(), bytes);
 

Приведенный выше пример, конечно, не работает, я просто ищу способ использовать какой-нибудь подстановочный assertArrayEquals() знак.

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


Благодаря ответу от JB Nizet у меня теперь есть следующий код, который работает просто отлично:

 private static int any() {
    return -1;
}

private static void assertArrayEquals(int[] expected, byte[] actual) {
    if(actual.length != expected.length) {
        fail(String.format("Arrays differ in size: expected <%d> but was <%d>", expected.length, actual.length));
    }

    for(int i = 0; i < expected.length; i   ) {
        if(expected[i] == -1) {
            continue;
        }

        if((byte) expected[i] != actual[i]) {
            fail(String.format("Arrays differ at element %d: expected <%d> but was <%d>", i, expected[i], actual[i]));
        }
    }
}
 

Ответ №1:

Вы могли бы просто записать ожидаемый массив в виде массива целых чисел и использовать специальное значение (например, -1) для представления подстановочного знака. Это тот же трюк, что и методы чтения входных потоков. Вам просто нужно будет написать свой заказ assertEqualsWithWildCard(int[] expected, byte[] actual) .

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

1. Простое, но понятное решение. Почему я не подумал об этом? Я добавил код к своему вопросу.

2. Может быть, использование a Byte[] было бы более уместным? Тогда подстановочные знаки будут null . Это был бы один из немногих случаев, когда a Byte[] был действительно полезен 😉

3. @Joachim: преимущество использования целых чисел также заключается в возможности легко записывать байтовые литералы: 0xBC против (байта) 0xBC

4. @JB: Я вижу, в этом случае код в ответе неверен «, хотя. Потому что byte в строке отсутствует приведение к if(expected[i] != actual[i]) : Так и должно быть if ((byte) expected[i] != actual[i]) .

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

Ответ №2:

Если вы собираетесь писать много подобного кода, я бы написал отдельный класс для «декодирования» пакета в значимые поля. Затем (конечно, после проверки того, что сам класс работает) вы можете написать разумные тесты, такие как

 assertEquals(42, packet.length());
assertEquals(0xDEADBEEF, packet.checksum());
 

и т.д.

Таким образом, вы не «пропускаете случайные байты», и ваш код будет намного более читабельным (если немного более подробным).

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

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