Beanie
Testing is important to guarantee the functionality of an application. These tests often rely on complex data structure as input.
Beanie helps with the construction of these input beans, making tests as readable and understandable as possible, promoting reuse of input data over multiple tests. Beans are constructed using the BeanBuilder
API:
Person person =
builder.start(Person.class) // Construct person
.withValue("email", "[email protected]") // Set email
.withValue("hobbies", "coding") // Add hobbies
.withValue("hobbies", "gaming") // Add hobbies
.generateValue("name", new RandomStringGenerator(8, 12)) // Generate name
.fill() // Generate other values (irrelevant for this test)
.save(); // Construct and persist the person
Or define a custom builder interface for your data type. This allows for more type-safe data creation and even allows us to define default 'convenience' methods:
public interface PersonBuilder extends EditableBeanBuildCommand<Person> {
PersonBuilder withEmail(String email);
PersonBuilder withName();
PersonBuilder withName(String name);
PersonBuilder withName(ValueGenerator generator);
PersonBuilder withHobbies(String hobby);
PersonBuilder withHobbies(Set<String> hobbies);
default PersonBuilder coder() {
return this.withHobbies("coding");
}
}
Custom builders are also started using the BeanBuilder
:
Person person =
builder.startAs(PersonBuilder.class)
.withEmail("[email protected]")
.withName("Jan")
.coder()
.save();
Specific builder
It is recommended to create a specific builder per type of bean. This type specific builder can have factory methods, such as jan()
, which get used in multiple unit tests:
@Component
@AllArgsConstructor
public class Persons {
private final BeanBuilder builder;
public Person jan() {
return builder.startAs(PersonBuilder.class)
.withEmail("[email protected]")
.withName("Jan")
.coder()
.save();
}
}
Usage of builders keeps our unit test simple and concise:
public class PersonServiceTest {
private PersonService personService;
private Persons persons;
@Test
public void change_email() {
Person jan = persons.jan();
Person updated = personService.changeEmail(jan, "[email protected]");
assertEquals("[email protected]", updated.getEmail());
}
}
Getters and setters
Test the getter and setter methods for all beans in a package, using this one liner:
new BeanTester().includeAll().verifyBeans("some.package");
Bean tester will scan the package for beans and verify the getter/setter methods, using both null
and non-null
generated values. This way we test the consistency of changing a property and retrieving it afterwards.
License
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.