I would like to know what is the best approach in order to unit test objects with nested properties.
This is the structure I'm using. ContainerType
is a sort of wrapper object. It contains two String
properties and an HolderList
property. HolderList
is an object that contains a list of Holder
s and so on. The model is like this one because I'm using JAXB in order to generate an XML output.
public class Container
{
private String code;
private String description;
private HolderList holderList;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public HolderList getHolderList() {
return holderList;
}
public void setHolderList(HolderList holderList) {
this.holderList = holderList;
}
public static class HolderList
{
private List<Holder> holders;
public List<Holder> getHolders() {
return holders;
}
public void setHolders(List<Holder> holders) {
this.holders = holders;
}
}
public static class Holder
{
private String code;
private GroupList groupList;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public GroupList getGroupList() {
return groupList;
}
public void setGroupList(GroupList groupList) {
this.groupList = groupList;
}
}
public static class GroupList
{
private List<Group> groups;
public List<Group> getGroups() {
return groups;
}
public void setGroups(List<Group> groups) {
this.groups = groups;
}
}
public static class Group
{
private String code;
private TitleList titleList;
public TitleList getTitleList() {
return titleList;
}
public void setTitleList(TitleList titleList) {
this.titleList = titleList;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}
public static class TitleList
{
private List<Title> titles;
public List<Title> getTitles() {
return titles;
}
public void setTitles(List<Title> titles) {
this.titles = titles;
}
}
public static class Title
{
private String code;
private String description;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
}
My approach would be like this, but I think unit tests will become unreadable. In addition this pattern is not developer friendly.
Container container = operation.getContainer(request);
assertNotNull(container);
assertEquals("0", container.getOutcomeCode());
assertEquals(1, container.getHolderList().getHolders().size());
assertEquals("123456", container.getHolderList().getHolders().get(0).getCode());
assertEquals(2, container.getHolderList().getHolders().get(0).getGroupList().getGroups().size());
assertEquals("123456", container.getHolderList().getHolders().get(0).getGroupList().getGroups().get(0).getCode());
assertEquals(1, container.getHolderList().getHolders().get(0).getGroupList().getGroups().get(0).getTitleList().getTitles().size());
assertEquals("123456", container.getHolderList().getHolders().get(0).getGroupList().getGroups().get(1).getCode());
assertEquals(7, container.getHolderList().getHolders().get(0).getGroupList().getGroups().get(1).getTitleList().getTitles().size());
// additional asserts here
Do you suggest any other approach?
Update
Within operation.getContainer
I'm creating a ContainerType
with all nested its nested properties. The marshalling with JAXB is done after this step. So, I would like to test this method in order to verify the method returns the expected object. Does this test make sense?
1 Answer 1
The approach with HolderList
+ Holder
definitions is indeed extremely hard to maintain.
There is no need to create intermediate wrapper objects like HolderList
, because JAXB supports annotations and the same output can be achieved by using:
@XmlRootElement
public class Container {
private String code;
private String description;
@XmlElementWrapper(name = "holderList")
private List<Holder> holders;
}
The three *List
classes are thus removed from the original code.
I can also suggest to extract all the nested classes (Holder
, Group
, Title
) to their dedicated files: this simplifies the structure, makes it easier to navigate and is simply cleaner.
Update:
The arguments to assertEquals
can be refactored with shortcut methods:
private static Holder getFirstHolder(Container container) {
return container.getHolders().get(0);
}
// and
assertEquals("123456", getFirstHolder(container).getCode());
and so on.
-
\$\begingroup\$ Thank you very much for your reply. Yep, it will definitely help my structure and my uni tests as well. Do you have any suggestion for the unit-test part? \$\endgroup\$Lorenzo B– Lorenzo B2017年08月01日 14:24:19 +00:00Commented Aug 1, 2017 at 14:24
-
\$\begingroup\$ Concerning the unit tests part, it really depends on what you want to test. Usually, tests on POJOs that contain only getters/setters do not add much value. I updated the answer with a short idea about the assertions. \$\endgroup\$Antot– Antot2017年08月01日 14:38:07 +00:00Commented Aug 1, 2017 at 14:38
-
\$\begingroup\$ Thanks. The think I'm testing here is
operation.getContainer()
. \$\endgroup\$Lorenzo B– Lorenzo B2017年08月01日 14:39:50 +00:00Commented Aug 1, 2017 at 14:39 -
\$\begingroup\$ Within
operation.getContainer
I'm creating aContainerType
with all its nested properties. The marshalling with JAXB is done after this step. So, I would like to test this method in order to verify the method returns the expected object. Does this test make sense? Thanks. \$\endgroup\$Lorenzo B– Lorenzo B2017年08月01日 15:09:57 +00:00Commented Aug 1, 2017 at 15:09 -
1\$\begingroup\$ Yes, sure, it is necessary to test the contents of the result returned by
operation.getContainer
. \$\endgroup\$Antot– Antot2017年08月01日 15:30:01 +00:00Commented Aug 1, 2017 at 15:30