Существует ли такая платформа, как Factory Girl для Java?

Factory Девушка - удобная структура в рельсах для легкого создания экземпляров моделей для тестирования.

Из Factory Домашняя страница девушки:

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

Пример (также с домашней страницы):

Factory.sequence :email do |n|
    "somebody#{n}@example.com"
end

# Let define a factory for the User model. The class name is guessed from the
# factory name.
Factory.define :user do |f|
    # These properties are set statically, and are evaluated when the factory is
    # defined.
    f.first_name 'John'
    f.last_name  'Doe'
    f.admin      false
    # This property is set "lazily." The block will be called whenever an
    # instance is generated, and the return value of the block is used as the
    # value for the attribute.
    f.email      { Factory.next(:email) }
end

если мне нужен пользователь a, можно просто вызвать

test_user = Factory(:user, :admin => true)

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

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

P.S: Я знаю как JMock, так и EasyMoc, однако я не говорю о насмешливой структуре здесь.

Ответ 1

Одна из возможных библиотек для этого - Usurper.

Однако, если вы хотите указать свойства объектов, которые вы создаете, то статическая типизация Java делает структуру бессмысленной. Вам нужно будет указать имена свойств в виде строк, чтобы инфраструктура могла искать аксессуры свойств с использованием рефлексии или Java Bean самоанализа. Это сделает рефакторинг намного сложнее.

Это намного проще, чем просто создавать новые объекты и вызывать их методы. Если вы хотите избежать множества шаблонов кода в тестах, может помочь шаблон Test Data Builder.

Ответ 2

Я также искал Java-эквивалент Factory Girl, но так и не нашел ничего подобного. Вместо этого я создал решение с нуля. A Factory для генерации моделей в Java: Model Citizen.

Вдохновленный Factory Girl, он использует аннотации полей для установки значений по умолчанию для модели, простой пример из вики:

@Blueprint(Car.class)
public class CarBlueprint {

    @Default
    String make = "car make";

    @Default
    String manufacturer = "car manufacturer";

    @Default
    Integer mileage = 100;

    @Default
    Map status = new HashMap();
}

Это будет модель Blueprint для модели автомобиля. Это зарегистрировано в ModelFactory, а новые экземпляры могут быть созданы следующим образом:

ModelFactory modelFactory = new ModelFactory();
modelFactory.registerBlueprint( CarBlueprint.class );
Car car = modelFactory.createModel(Car.class);

Вы можете переопределить значения модели автомобиля, передав экземпляр Car вместо класса и установив значения по мере необходимости:

Car car = new Car();
car.setMake( "mustang" );
car = modelFactory.createModel( car );

wiki содержит более сложные примеры (такие как использование @Mapped) и подробности для еще нескольких колоколов и свистков.

Ответ 3

  • Я понимаю, что это не для всех, но вы можете написать тестовый код Ruby против вашего Java-кода. (JTestR)
  • Предпочтительный способ сделать это в Java - это использовать шаблон Test Data Builder. Я бы сказал, что этот подход на самом деле не требует введения сложностей каркаса или внешней зависимости. Я просто не понимаю, как вы могли бы указать гораздо меньше, используя фреймворк и получить от него что-то еще... Синтаксис Builder по сути эквивалентен вашему синтаксису FactoryGirl. (Кто-то не стесняется убеждать меня иначе!)

Ответ 4

Я знаю, что это не совсем то, что вы ищете...

В прошлом я написал код, который использует отражение для заполнения значений beans. Основная идея состоит в том, чтобы найти все сеттеры и называть каждого с фиктивным значением. Моя версия установила все строки, так как имя поля setName будет вызываться с именем "name", а затем установить все int как 1, booleans на true и т.д.

Затем я использовал это в сочетании с шаблонами, аналогичными объектам Mother и Test Data Builder.

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

Надеюсь, что это поможет.

Ответ 5

Я пришел сюда с тем же вопросом и нуждался в инструменте для создания данных для своих тестов интеграции. Я решил принять вызов с Groovy, который является моим языком выбора для тестов из-за его компактности и power assert.

Я только что написал небольшой помощник https://gist.github.com/pgaertig/9502960 под названием FactoryGrill;), который позволяет писать сценарии данных, как показано ниже.

insert('MyTable', ID: 1, CREATED_AT: new Date(), NAME: 'Example text')

выше эквивалентно:

INSERT INTO MyTable(ID, CREATED_AT, NAME) VALUES (1, ..current date here.., 'Example text')

Вы можете сделать больше с помощью Groovy:

import org.apache.commons.lang3.RandomStringUtils;

for ( i in 0..9 ) {
     insert('USERS', CREATED_AT: new Date(), EMAIL: "test${i}@mydomain.com",
                     SALT: RandomStringUtils.randomAlphanumeric(32));
}

load(new File('usersettings.groovy').text)    //script nesting etc

Это действительно не factory, потому что фабрики довольно прямолинейны в Groovy с конструктором карты или expandos.

Ссылки и другие материалы от FactoryGirl недоступны в настоящее время, потому что выше достигается только с ~ 30LOC. Однако, если есть интерес к моему решению, я добавлю специальный проект на Github.

Ответ 6

Если ваши объекты модели просты, нет оснований использовать фреймворк для их создания, просто используйте "новый" оператор. Если у вас сложная модель (сложные отношения), вы можете использовать spring для их связывания (даже в тестовых сценариях вы можете использовать spring)

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