So I have a webproject with Hybris, Spring and so on.
I have some classes, which are autogenerated. Let's say I have one modelclass, which is autogenerated and inherits from another class some methods, to set fields.
When writing Unit-tests, is it useful to start using the Builder pattern? Because the thing is, I don't have a constructor, like Employee(int id, String name) and so on, I only have the inherited methods to set them (setId(int id) and so on).
So when I would write a Builder class for this model for example, I would have the methods .withId(int id) and .withName(String name) and the build()-method, where I would run the setter-methods.
so in the end in my test-class I would have:
EmployeeBuilder eb = new EmployeeBuilder();
Employee emp = eb.withId(123)
.withName("John")
.build();
But since I already have Setter-Methods I normally have:
Employee emp = new Employee();
emp.setId(123);
emp.setName("John");
So is it really worth the effort in this case? Or is there something I have not really understood?
Thanks!
Before I give an answer to your question I would like to explain the builder pattern.
The builder pattern is usually used when you have a lot of overloaded constructors (telescoping constructor anti-pattern). E.g.
public class Employee {
public Employee(String firstName, String lastName){
...
}
public Employee(String firstName, String lastName, Sex sex){
...
}
public Employee(String firstName, String lastName, String salutation) {
...
}
}
In this case client code must decide which constructor to invoke depending on the data it has. If it has a firstName
and lastName
it must invoke new Employee(firstName, lastName)
. If it only has a firstName
it must invoke Employee(String firstName)
. So the client code might have a lot of if/then/else. E.g.
Employee employee = null;
if(firstName != null && lastName != null && sex != null){
employee = new Employee(firstName, lastName, sex);
} else if(firstName != null && lastName != null && salutation != null){
employee = new Employee(firstName, lastName, salutation );
} else {
.....
}
The design of the Employee
class in this example includes that firstName
and lastName
are mandatory attributtes of an Employee
, because every constructor needs them. The attributes sex
and saluation
are optional. If the client code decides which constructor to invoke this also means that the decision process is duplicated accross client code. E.g. if a client knows the firstName
, lastName
, sex
and salutation
which constructor should it call? Either new Employee(firstName, lastName, sex)
or new Employee(firstName, lastName, saluation)
?
In order to encapsulate the constructor resolution you might want to use a builder pattern.
public class EmployeeBuilder {
public EmployeeBuilder(String firstName, String lastName){
}
public void setSex(Sex sex){ ... }
public void setSalutation(Salutation salutation){ ... }
public Employee build(){
if(salutation != null){
return new Emplyoee(firstName, lastName, salutation);
} else if(sex != null){
return new Emplyoee(firstName, lastName, sex);
} else {
return new Emplyoee(firstName, lastName);
}
}
}
This makes the client-code much easier to read and the constructor invokation decision is encapsulated. E.g.
EmployeeBuidler employeeBuilder = new EmployeeBuilder(firstName, lastName);
Sex sex = ...;
String salutation = ...;
employeeBuilder.setSex(sex);
employeeBuilder.setSalutation(salutation);
Employee employee = employeeBuilder.build();
Back to your question
So is it really worth the effort in this case?
For your unit tests you might want to create Employee
objects with some attributes and the others should be set to default values. In this case I think it is a good idea to use a builder pattern. I would name the builder then e.g. EmployeeDefaultValuesBuilder
to make it clear.
You might also want to build Employee
s based on other employee objects (templates). In this case I would add another constructor to the EmployeeBuilder
. E.g.
public EmployeeBuilder(Employee template){
// initialize this builder with the values of the template
}
So it is worth the effort if you encapsulate construction logic or if it increases readability.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With