When you have to work with complex nested object structures and you want an easy way to create them and test them, I think it's definitely worthwhile to create a builder. A builder is a fluent DSL to create (domain) objects. Below you can see how that works out
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.pelssers.domain; | |
public class Person { | |
private String firstName; | |
private String lastName; | |
public String getFirstName() { | |
return firstName; | |
} | |
public void setFirstName(String firstName) { | |
this.firstName = firstName; | |
} | |
public String getLastName() { | |
return lastName; | |
} | |
public void setLastName(String lastName) { | |
this.lastName = lastName; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.pelssers.domain; | |
public class PersonBuilder { | |
private String firstName; | |
private String lastName; | |
/** | |
* @param person the source person | |
* @return a new personbuilder object with all properties from person copied | |
*/ | |
public static PersonBuilder from(Person person) { | |
return | |
new PersonBuilder() | |
.withFirstName(person.getFirstName()) | |
.withLastName(person.getLastName()); | |
} | |
public Person build() { | |
Person person = new Person(); | |
person.setFirstName(firstName); | |
person.setLastName(lastName); | |
return person; | |
} | |
public PersonBuilder withFirstName(String firstName) { | |
this.firstName = firstName; | |
return this; | |
} | |
public PersonBuilder withLastName(String lastName) { | |
this.lastName = lastName; | |
return this; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.pelssers.domain; | |
import org.junit.Assert; | |
import org.junit.Before; | |
import org.junit.Test; | |
public class PersonBuilderTest { | |
private static final String PELSSERS = "Pelssers"; | |
private static final String ROBBY = "Robby"; | |
private static final String DAVY = "Davy"; | |
private static final String WILLIAMS = "Williams"; | |
private Person robby; | |
private Person davy; | |
@Before | |
public void setUp() { | |
robby = | |
new PersonBuilder() | |
.withFirstName(ROBBY) | |
.withLastName(PELSSERS).build(); | |
davy = | |
PersonBuilder | |
.from(robby) | |
.withFirstName(DAVY).build(); | |
} | |
@Test | |
public void testRobby() { | |
Assert.assertEquals(PELSSERS, robby.getLastName()); | |
Assert.assertEquals(ROBBY, robby.getFirstName()); | |
} | |
@Test | |
public void testDavy() { | |
Assert.assertEquals(PELSSERS, davy.getLastName()); | |
Assert.assertEquals(DAVY, davy.getFirstName()); | |
} | |
@Test | |
public void testFromCreatesNewObject() { | |
//davy is build with a builder created from robby | |
//now check if we change robby's lastname this does not affect davy | |
robby.setLastName(WILLIAMS); | |
Assert.assertEquals(WILLIAMS, robby.getLastName()); | |
Assert.assertEquals(PELSSERS, davy.getLastName()); | |
} | |
} |