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

Factory Girl — это удобный фреймворк на рельсах для простого создания экземпляров моделей для тестирования.

С главной страницы Factory Girl:

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

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

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

# Let's 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

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

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

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

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

P.S: я знаю и JMock, и EasyMoc, однако я не говорю здесь о мок-фреймворке.


person KaptajnKold    schedule 12.06.2009    source источник
comment
Можете ли вы привести пример того, как FactoryGirl делает так, чтобы нам не приходилось идти и читать об этом где-то еще?   -  person skaffman    schedule 12.06.2009
comment
Был один для Python, пока эти союзы по защите прав разработчиков не начали мешать!   -  person Aiden Bell    schedule 12.06.2009
comment
Beanmother github.com/keepcosmos/beanmother — это то, что вам нужно.   -  person Jaehyun Shin    schedule 16.10.2017


Ответы (6)


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

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

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

person Nat    schedule 14.06.2009
comment
Хорошо сказано - я бы принял этот ответ, если бы это был мой вопрос. :) - person cwash; 24.06.2009
comment
Make it easy чем-то похож, поскольку помогает реализовать построители тестовых данных. , которые определяют значения по умолчанию для каждого свойства. - person Augusto; 05.04.2011
comment
Ссылка узурпатора не работает, проект, похоже, мертв. - person Thiago Negri; 26.05.2016

Я также искал Java-эквивалент Factory Girl, но ничего подобного не нашел. Вместо этого я создал решение с нуля. Фабрика для создания моделей на 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();
}

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

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

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

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

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

person mguymon    schedule 04.09.2012

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

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

В прошлом я написал некоторый код, который использует отражение для заполнения значений bean-компонентов. Основная идея состоит в том, чтобы найти все сеттеры и вызвать каждый с фиктивным значением. Моя версия установила все строки, так как имя поля setName будет вызываться с «именем», затем установить все целые числа как 1, логические значения равны истине и т. д.

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

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

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

person Pablojim    schedule 14.06.2009

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

Я только что написал небольшой помощник 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

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

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

person gertas    schedule 12.03.2014

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

  • но это просто для объектов данных, если вы говорите о создании экземпляров объектов, которые что-то делают, рекомендуется имитировать/заглушать внешние отношения вместо использования реальных экземпляров.
person silmx    schedule 12.06.2009
comment
Если ваши объекты модели просты, то это не так :-) вы можете использовать Spring, чтобы связать их вместе. Можете ли вы немного рассказать об этом? Допустим, у меня есть модель Movie, у Movie есть несколько потоков, у каждого потока есть хост. Теперь я хотел бы 25 фильмов для целей тестирования. Как мне помогает Spring? Что, если мне нужно 25 фильмов в базе данных, чтобы проверить мои методы поиска? - person KaptajnKold; 12.06.2009
comment
Я бы не рекомендовал пытаться создавать их с использованием ключевого слова «новое» для объектов любой сложности. По крайней мере, вы хотели бы использовать шаблон Object Mother (по сути, создавать статические фабричные методы для обычно инициализируемых объектов), но в идеале вы должны использовать шаблон Builder, потому что он предоставляет вам разумные значения по умолчанию и механизм для переопределения свойств на детальном уровне. - person cwash; 13.06.2009
comment
Я думаю, вы смешиваете здесь слишком много вещей. - Например, для тестирования кода базы данных у вас есть DBUnit, который помогает вам управлять базой данных до и после тестирования. - для юнит-теста не нужно 25 фильмов, достаточно 2 или 3 для юнит-теста класса. Мое мнение таково... попробуйте упростить свои тесты, и вы увидите, что вам не нужна структура для создания входных данных для теста. - person silmx; 15.06.2009
comment
Когда вы накапливаете много юнит-тестов, и для простоты все они обновляют свои собственные объекты. Когда один из этих объектов добавляет параметр в конструктор где-то теперь, вам нужно изменить 50 объектов, чтобы учесть это. Или, что еще хуже, изменение происходит в глубоко вложенном объекте предметной области. Вот почему люди рекомендуют использовать Object Mothers или Test Data Builders (или Factory Girl, если вы используете Ruby) — чтобы ваши модульные тесты не были слишком сложными в обслуживании. Когда они есть, люди перестают их писать или просто комментируют, что противоречит цели. - person cwash; 24.06.2009