Junit Test Setters и Getters из экземпляров переменных

При создании тестовых примеров для сеттеров и получателей переменных экземпляра внутри объекта. Каков наилучший подход? Здесь я использую методы get и set в своих тестах. Будет ли это плохой стратегией тестирования?

/**
 * Test of setFlightNumber method, of class Flight.
 */
@Test
public void testSetFlightNumber() {
    System.out.println("setFlightNumber");
    int flightNumber = 1000;
    Flight instance = new Flight();
    instance.setFlightNumber(flightNumber);
    // TODO review the generated test code and remove the default call to fail.
    assertEquals(instance.getFlightNumber(), flightNumber);
}

/**
 * Test of getFlightNumber method, of class Flight.
 */
@Test
public void testGetFlightNumber() {
    System.out.println("getFlightNumber");
    Flight instance = new Flight();
    int expResult = 1000;
    instance.setFlightNumber(1000);
    int result = instance.getFlightNumber();
    assertEquals(expResult, result);
}

Ответ 1

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

Это означает, что мы не можем использовать метод get в нашем тесте set, и наоборот - вы не тестируете отдельную единицу кода, которая является единственным методом.

Учитывая, что...

Скажем, мы имеем a PlainOldJavaObject с полем value, которое мы хотим (по какой-то причине) проверить для обоснованности сеттеров и геттеров. Единственный подходящий способ сделать это - использование отражения.

Здесь мое объявление класса, которое довольно тощее:

public class PlainOldJavaObject {

    private String value;

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

Теперь я настроил свой тестовый класс, чтобы использовать отражение; специально используя класс Field:

public class PlainOldJavaObjectTest {

    @Test
    public void testSetter_setsProperly() throws NoSuchFieldException, IllegalAccessException {
        //given
        final PlainOldJavaObject pojo = new PlainOldJavaObject();

        //when
        pojo.setValue("foo");

        //then
        final Field field = pojo.getClass().getDeclaredField("value");
        field.setAccessible(true);
        assertEquals("Fields didn't match", field.get(pojo), "foo");
    }

    @Test
    public void testGetter_getsValue() throws NoSuchFieldException, IllegalAccessException {
        //given
        final PlainOldJavaObject pojo = new PlainOldJavaObject();
        final Field field = pojo.getClass().getDeclaredField("value");
        field.setAccessible(true);
        field.set(pojo, "magic_values");

        //when
        final String result = pojo.getValue();

        //then
        assertEquals("field wasn't retrieved properly", result, "magic_values");
    }

}

В первом тесте я уверен, что поле считывается путем отражения доступа к значению, содержащемуся в поле для экземпляра PlainOldJavaObject. Не нарушая целостность объявленного класса *, я уверен, что поле устанавливается соответствующим образом.

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

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

*: Имейте в виду, что рефлексия - быстрый и быстрый способ вступить в экстремальные проблемы с поведением undefined, и у вас мало гарантий неизменности объекта. Вы снимаете термоусадочную пленку с языка и делаете странные и необычные вещи. Действуйте на свой страх и риск.

Ответ 2

Использовать Bean API-интерфейс Runner

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

testBean

public void testBean(java.lang.Object bean)
              throws java.lang.Exception
Test the properties that have both getters and setters. Exclude those who have been excluded by excludeProperty(String). If the object implements Serializable, do a check to ensure it really is.
Parameters:
bean - the object to test
Throws:
java.lang.Exception - on failure

Ответ 3

Я считаю, что тестирование getter/setter имеет значение, поскольку оно может ловить опечатки. Однако на них нужно потратить очень мало времени, поскольку эти ошибки не часто возникают из-за инструментов генерации кода. Следовательно, использование инструмента для выполнения этих тестов, а не для их написания, является хорошей практикой.

Вот почему я создал ReflectiveGetterSetterTester, у которого есть метод testAllGetterSetters

ReflectiveGetterSetterTester

Другие примечания...

  • Нет необходимости использовать два метода тестирования. Используйте его, поскольку он будет выполнять как приемник, так и сеттер.
  • Рассмотрите возможность использования Theory для проверки диапазона допустимых значений (0, 1, Integer.MAX_VALUE). Вы также можете использовать TestedOn для передачи этого int in-line здесь
  • Проверить условия ошибки, такие как передача -1

Ответ 4

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

  • использовать отражение

  • пометить ваше личное поле как защищенное и наследовать ваш тест от цели,

  • или не проверяйте геттеры и сеттеры

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