4
\$\begingroup\$

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 Holders 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?

\$\endgroup\$
1
\$\begingroup\$

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.

\$\endgroup\$
  • \$\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 Aug 1 '17 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 Aug 1 '17 at 14:38
  • \$\begingroup\$ Thanks. The think I'm testing here is operation.getContainer(). \$\endgroup\$ – Lorenzo B Aug 1 '17 at 14:39
  • \$\begingroup\$ Within operation.getContainer I'm creating a ContainerType 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 Aug 1 '17 at 15:09
  • 1
    \$\begingroup\$ Yes, sure, it is necessary to test the contents of the result returned by operation.getContainer. \$\endgroup\$ – Antot Aug 1 '17 at 15:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.