Фиктивные данные и стратегии модульного тестирования в модульном стеке приложений

Как вы управляете фиктивными данными, используемыми для тестов? Хранить их вместе с соответствующими сущностями? В отдельном тестовом проекте? Загружать их с помощью сериализатора из внешних ресурсов? Или просто воссоздавать их там, где это необходимо?

У нас есть стек приложений с несколькими модулями, зависящими друг от друга, каждый из которых содержит сущности. Каждый модуль имеет свои собственные тесты и нуждается в фиктивных данных для работы.

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

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

Есть ли лучший практический выход из этого положения или все решения являются компромиссами?


Подробнее

Наш стек выглядит примерно так:

Один модуль:

src/main/java --> gets jared (.../entities/*.java contains the entities)
src/main/resources --> gets jared
src/test/java --> contains dummy object setup, will NOT get jared
src/test/resources --> not jared

Мы используем Maven для обработки зависимостей.

Пример модуля:

  • Модуль A имеет несколько фиктивных объектов
  • Модулю B нужны свои объекты И такие же, как у модуля A

Вариант a)

Тестовый модуль T может хранить все фиктивные объекты и предоставлять их в тестовой области видимости (так что загруженные зависимости не пострадают) всем тестам во всех модулях. Будет ли это работать? Имеется в виду: Если я загружу T в A и запущу install на A, он НЕ будет содержать ссылок, введенных T, особенно не B? Тогда, однако, A будет знать о датамодели B.

Вариант б)

Модуль A предоставляет фиктивные объекты где-то в src/main/java../entities/dummy, позволяя B получить их, а A не знает о фиктивных данных B

Вариант в)

Каждый модуль содержит внешние ресурсы, которые являются сериализованными фиктивными объектами. Они могут быть десериализованы тестовой средой, которой они нужны, поскольку она имеет зависимость от модуля, которому они принадлежат. Однако это потребует, чтобы каждый модуль создавал и сериализовывал свои фиктивные объекты, а как это сделать? Если с другим модульным тестом, то это введет зависимости между модульными тестами, чего никогда не должно происходить, или со скриптом, это будет трудно отлаживать и не гибко.

Вариант d)

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

Чего мы не хотим

Мы не хотим создавать статическую базу данных со статическими данными, поскольку структура требуемых объектов будет постоянно меняться. Много сейчас, немного позже. Поэтому мы хотим, чтобы hibernate создал все таблицы и колонки и заполнил их данными во время модульного тестирования. Кроме того, статическая база данных внесет много потенциальных ошибок и тестовых взаимозависимостей.


В правильном ли направлении идут мои мысли? Как лучше всего поступать с тестами, требующими большого количества данных? У нас будет несколько взаимозависимых модулей, которые будут требовать объекты, заполненные какими-то данными из нескольких других модулей.


EDIT

Немного дополнительной информации о том, как мы делаем это сейчас, в ответ на второй ответ:

Итак, для простоты, у нас есть три модуля: Person, Product, Order. Person будет тестировать некоторые методы менеджера, используя объект MockPerson:

person/src/test/java:)

public class MockPerson {

    public Person mockPerson(parameters...) {
        return mockedPerson;
    }
}

public class TestPerson() {
    @Inject
    private MockPerson mockPerson;
    public testCreate() {
        Person person = mockPerson.mockPerson(...);
        // Asserts...
    }
}

Класс MockPerson не будет упакован.

То же самое относится к тестам Product:

product/src/test/java:)

public class MockProduct() { ... }
public class TestProduct {
    @Inject
    private MockProduct mockProduct;
    // ...
}

MockProduct необходим, но не будет упакован.

Теперь для тестов заказа потребуются MockPerson и MockProduct, поэтому сейчас нам нужно создать оба, а также MockOrder для тестирования Order.

order/src/test/java:)

Это дубликаты и их нужно будет менять каждый раз, когда Person или Product изменится

public class MockProduct() { ... }
public class MockPerson() { ... }

Это единственный класс, который должен быть здесь:

public class MockOrder() { ... }

public class TestOrder() {
    @Inject
    private order.MockPerson mockPerson;
    @Inject
    private order.MockProduct mockProduct;
    @Inject
    private order.MockOrder mockOrder;
    public testCreate() {

        Order order = mockOrder.mockOrder(mockPerson.mockPerson(), mockProduct.mockProduct());
        // Asserts...
    }
}

Проблема в том, что теперь нам нужно обновить person. MockPerson и order.MockPerson при каждом изменении Person.

Не лучше ли просто опубликовать Mocks вместе с jar, чтобы каждый другой тест, у которого есть зависимость, мог просто вызвать Mock.mock и получить красиво настроенный объект? Или это темная сторона - легкий путь?

10
задан Pete 6 February 2014 в 06:27
поделиться