A library for setting up Java objects as test data, inspired in Factory Bot
Maven:
<dependency>
<groupId>br.com.leonardoferreira</groupId>
<artifactId>JBacon</artifactId>
<version>2.1.1</version>
<scope>test</scope>
</dependency>
Gradle:
testImplementation "br.com.leonardoferreira:JBacon:2.1.1"
It is recommended use with some fake data generator lib like java-faker
Define factory class:
@Component
public class ContactFactory extends JBacon<Contact> {
@Autowired
private ContactRepository contactRepository;
@Autowired
private Faker faker;
@Override
protected Contact getDefault() {
Contact contact = new Contact();
contact.setName(faker.name().fullName());
contact.setEmail(faker.internet().emailAddress());
contact.setPhone(faker.phoneNumber().phoneNumber());
return contact;
}
@Override
protected Contact getEmpty() {
return new Contact();
}
@Override
protected void persist(Contact contact) {
contactRepository.save(contact);
}
}
// Returns a Contact instance that not saved, based on default
Contact build = contactFactory.build();
// Returns a list of Contact instance that not saved, based on default
List<Contact> buildList = contactFactory.build(5);
// Returns a saved Contact instance, based on default
Contact create = contactFactory.create();
// Returns a saved list of Contact instance, based on default
List<Contact> createList = contactFactory.create(5);
JBacon allows create object based on example.
// All contacts create/build with this example will have "Leonardo Ferreira" as name,
// and others attributes will be fill based on getDefault
Contact example = new Contact();
example.setName("Leonardo Ferreira");
Contact build = contactFactory.build(example);
List<Contact> buildList = contactFactory.build(5, example);
Contact create = contactFactory.create(example);
List<Contact> createList = contactFactory.create(5, example);
Other example syntax supported:
Contact build = contactFactory.build(empty -> {
empty.setName("Leonardo Ferreira");
empty.setEmail("[email protected]");
});
List<Contact> buildList = contactFactory.build(5, empty -> {
empty.setName("Leonardo Ferreira");
empty.setEmail("[email protected]");
});
Contact create = contactFactory.create(empty -> {
empty.setName("Leonardo Ferreira");
empty.setEmail("[email protected]");
});
List<Contact> createList = contactFactory.create(5, empty -> {
empty.setName("Leonardo Ferreira");
empty.setEmail("[email protected]");
});
@Component
public class ContactFactory extends JBacon<Contact> {
@Autowired
private ContactRepository contactRepository;
@Autowired
private Faker faker;
@Override
protected Contact getDefault() {
Contact contact = new Contact();
contact.setName(faker.name().fullName());
contact.setEmail(faker.internet().emailAddress());
contact.setPhone(faker.phoneNumber().phoneNumber());
return contact;
}
@JBaconTemplate("invalid")
protected Contact invalidContact() {
Contact contact = new Contact();
contact.setName(faker.name().fullName());
contact.setEmail("invalid_email");
contact.setPhone(faker.phoneNumber().phoneNumber());
return contact;
}
@Override
protected Contact getEmpty() {
return new Contact();
}
@Override
protected void persist(Contact contact) {
contactRepository.save(contact);
}
}
// Returns a Contact instance that not saved, based on invalid template
Contact build = contactFactory.build("invalid");
// Returns a list of Contact instance that not saved, based on invalid template
List<Contact> buildList = contactFactory.build(5, "invalid");
// Returns a saved Contact instance, based on invalid template
Contact create = contactFactory.create("invalid");
// Returns a saved list of Contact instance, based on invalid template
List<Contact> createList = contactFactory.create(5, "invalid");
When getDefault depends on creating another object, you can use:
public class PhoneFactory extends JBacon<Phone> {
@Autowired
private Faker faker;
@Autowired
private ContactFactory contactFactory;
@Autowired
private PhoneRepository phoneRepository;
@Override
protected Phone getDefault() {
Phone phone = new Phone();
phone.setNumber(faker.phoneNumber().phoneNumber());
phone.setContact(Lazy.of(Contact.class).with(contactFactory::create));
return phone;
}
@Override
protected Phone getEmpty() {
return new Phone();
}
@Override
protected void persist(final Phone phone) {
phoneRepository.save(phone);
}
}
Using this way, it's avoids save unnecessary objects, when uses example. Ex:
Contact contact = contactFacotory.create();
List<Phone> phones = phoneFactory.create(5, empty -> {
empty.setContact(contact);
});
Without Lazy this will persist 6 contacts. When uses lazy it will persist only one contact.
- Better project description :)
- Using lombok only in compile
- BuildList operation #2
- Large refactor in project structure
- JBacon first release 🍻
- Create operation
- CreateList operation
- Build operation