FactoryDuke is a java framework that lets you create objects as test data. All you have to do is define the templates for each of the classes that you want FactoryDuke to create objects from. After that, FactoryDuke takes care of the rest.
Have you ever heard of factory_girl a super cool Ruby framework? Well, FactoryDuke is pretty similar in its use.
Factory Duke is using a lot of lamdba, so it is only compatible with java 8
and higher.
- Simple & Fluent
- Type safe
- Fast (no reflection)
- Very light (Only one dependency)
Use it like a maven dependency on your project
<dependency>
<groupId>com.github.regis-leray</groupId>
<artifactId>factory-duke</artifactId>
<version>0.8</version>
</dependency>
FactoryDuke is a singleton object where you can register all of the templates. For example, you can define a template as follows:
FactoryDuke.define(User.class, u -> {
u.setLastName("Scott");
u.setName("Malcom");
u.setRole(model.Role.USER);
});
after you can use this definition
User user = FactoryDuke.build(User.class).toOne();
You can override some fields during the creation of the instance
User user = FactoryDuke.build(User.class, u -> u.setRole(Role.ADMIN)).toOne();
If you need a full control of the bean creation you can return the instance itself.
FactoryDuke.define(User.class, () -> {
User u = new User();
u.setLastName("Scott");
u.setName("Malcom");
u.setRole(model.Role.USER);
return u;
});
You can use factory inside a definition by using the supplier approach, which provide you the ability to extends Factory
FactoryDuke.define(User.class, "admin_user", () -> {
//create instance from the default definition of User.class
User u = FactoryDuke.build(User.class).toOne();
u.setRole(model.Role.ADMIN);
return u;
});
User user = FactoryDuke.build(User.class, "admin_user").toOne();
It is highly recommended that you have one factory for each class that provides the simplest set of attributes necessary to create an instance of that class.
public class UserFactory implements TFactory {
@Override
public void define(){
FactoryDuke.define(User.class, u -> {
u.setLastName("Scott");
u.setName("Malcom");
u.setRole(model.Role.USER);
});
}
}
Use load()
to load all factories definitions from the default locations : classpath:Factories, classpath:factories/**
,
FactoryDuke.load();
You can specify you own package
FactoryDuke.load("x.x.custom.package");
Example of loading templates with JUnit tests
@Before
public void setUp() {
FactoryDuke.load();
}
The templates are save in a static map, if you want to clear all the templates you need to call
FactoryDuke.reset();
Create a list / set of two exact same user
List<User> list = FactoryDuke.build(User.class).times(2).toList();
Set<User> sets = FactoryDuke.build(User.class).times(2).toSet()
If you need to use generator
// the default generator is starting at 1 and incrementing by 1
SequenceValuesGenerator<Long> ids = Generators.sequence();
// constant will return always the same sequence of values
SequenceValuesGenerator<String> names = Generators.values("Scott","John","Malcom");
FactoryDuke.define(User.class, "generator_users", u -> {
//each generator's id call will return a unique value (1,2,3,4,5, ...)
u.setId(ids.nextValue());
//each generator's name call will return a value ("Scott","John","Malcom","Scott","John","Malcom", ...)
u.setName(names.nextValue());
});
// will return 3 differents users
List<User> users = FactoryDuke.build(User.class, "generator_users").times(3).toList();
If you need to setup a share behavior(s) between cross factories definitions you can now register hook(s).
This hook(s) will be called before or/and after the build()
creation.
FactoryDuke.load().addAfterHook(System.out::println)
Also there is a way to disable the global callback for each object build
FactoryDuke.build(User.class).skipAfterHook(true).toOne();
Tips the global callback can be really usefull is you need to implement a persistence layer on specific Object (example with hibernate)
@Inject
private SessionFactory sessionFactory;
@Before
public void loadAndCustomCallback(){
FactoryDuke.load().addAfterHook(o ->{
if(o.getClass().isAnnotationPresent(Entity.class)){
sessionFactory.getCurrentSession().save(o);
}
});
}
FactoryDuke is distributed under the MIT licence