POJO and JavaBean testing using Bean-matchers

Last update: Jun 02, 2020

Project repo: https://github.com/gualtierotesta/blog-projects/tree/master/pojo-testing

The first reaction to the question “Should I unit test a data class?” is usually a big NO because there is no meaning to check a data class which contains boiler plate code (getter, setter, equals..) often generated by means of the IDE or by libraries like Lombok and Immutables.

Real world projects are, unfortunately, not so perfect and there are cases where unit testing a POJO or a JavaBean could make sense. Let me list some situations I have encountered.

1. Security sensitive fields

If the data class contains a security sensitive field like a password or an API token, this field should NOT be logged.

See what OWASP has to say about this problem: https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html#data-to-exclude

For this reason, the class should not include sensitive fields in the toString method.

2. Logging unfriendly fields

The data class can contain fields which are binary data or very long string. In this case, we should exclude these fields from the toString method to prevent them to bloat our logging files.

3. Non standard equals and hashCode methods

The standard way to implement an equals method is to compare, one by one, all fields in the class. Sometimes one field contains a “unique” identifier that makes other fields comparison useless or even dangerous.

For example, this field can contain the primary key column of the database record from which the POJO data has been extracted. In this case, the POJO equality could or should depend only on its primary key field and the equals (and hashCode) implementation should use just this field.

4. No args constructor (JavaBeans)

The JavaBean standard requires the presence of a no-args constructor, a constructor without parameters.

The compiler usually creates the no args constructor unless there are already other (non no-args ) constructors defined in the class.

At runtime, the library (for example, the JPA libraries) which rely on the no-args constructor presence will fail at runtime due to the missing no-args constructor.

One important remark: checking all above conditions using an unit test is a way to guarantee the correct behaviour of the data class along all project life. The class can be correctly implemented when created but, later, one developer, while adding a new field in the class, can wrongly regenerate the toString method, restoring the log of a password field, or forget to regenerate the equals/hashCode methods in the proper way.

Checking data class quality is also useful in legacy projects to detect improper classes definitions because unit class can be added aside the “main” classes, without disturbing the legacy code.

The Bean-matchers library

The Bean-matchers library, created by Orien Madgwick, let us test the class conditions to guarantee that all future changes in the class will not break them.

Project repo is at https://github.com/orien/bean-matchers

Let’s assume we have the following data class:

class BasicBean {
  private int id;
  private String string;
  private char[] password;
  private Long[] longArray;
  private String veryLongString;

  public LombokBean(final int id) {
    this.id = id;
  }

   // getter, setter, equals, hashCode, toString

Conditions we want to assure:

  1. the id field should be used to check equality and to generate the class hash
  2. the password field should not be logged because security sensible
  3. the veryLongString field should not be logged to avoid logging files bloating
  4. the class should have a no-args constructor to be used with JPA.

Using the Bean-matchers library, the test class can be:

@Test
public void testTheClassIsGoodJavaBean() {
  MatcherAssert.assertThat(BasicBean.class,
    CoreMatchers.allOf(
      // This is Java Bean so we want an empty constructor
      BeanMatchers.hasValidBeanConstructor(),
      // All fields should have getter and setter
      BeanMatchers.hasValidGettersAndSetters(),
      // Only the 'id' field in hashcode and equals
      BeanMatchers.hasValidBeanHashCodeFor("id"),
      BeanMatchers.hasValidBeanEqualsFor("id"),
      // Password and veryLongString fields should not 
      // be included in the toString method
      BeanMatchers.hasValidBeanToStringExcluding(
          "password", "veryLongString")
    ));
}

The Beans-matchers library create an instance of our BasicBean class and checks if all conditions we have defined on

  • the constructor
  • the getters and setters,
  • the equals method
  • the hashCode method
  • the toString method

are valid otherwise the test fails.

A test failure will alert us whenever a change in the BasicBean class breaks the above conditions. It is a kind of safety net.

For Lombok users

Using Lombok, we can implement our bean conditions using Lombok annotations. The following code is the equivalent version of the plain Java version reported above:

@Data
@NoArgsConstructor
@EqualsAndHashCode(of = "id")
@ToString(exclude = {"password", "veryLongString"})
public class LombokBean {
  private int id;
  private String string;
  private char[] password;
  private Long[] longArray;
  private String veryLongString;

  public LombokBean(final int id) {
    this.id = id;
  }
}

When using Lombok, I believe there is no need to have a unit test to check our bean conditions because, in general, we should not test third party libraries (Lombok in this case), but having it will not damage your project 😉

Final remarks

Another possible benefit of testing data classes, especially in legacy projects, is that their code coverage is easily 100%. This should not be the main purpose (remember, there is no meaning to test getter and setter) but a side effect which I’ve found useful: having the data classes at 100%, the low test coverage is due to the logic classes, the classes which contains the code which implement the application logic. They should be the main target of any test!

Review: Go Programming Blueprints – Solving Development Challenges with Golang

Go Programming Blueprints - Solving Development Challenges with Golang
Go Programming Blueprints – Solving Development Challenges with Golang by Mat Ryer
My rating: 4 of 5 stars

Updated post can be found on my new blog site.

Real world solutions in GO
This book is not a primer on GO Language (here I suggest “The GO Programming Language” by Donovan & Kernighan, Addison-Wesley) but it should be read just after learning the basic concepts of the language and its tool chain.
The author introduces and describes in details several important concepts about the GO way to program, to structure the code and to organize the projects.
The examples are clear and simple to be easily understood but, at the same time, they can be used in our own projects.
The first project is a web based chat application which introduces main web application concepts like HTML templates, requests routing, Websocket and Oauth protocols, JSON, images plus some GO specifics like how to use the channels to handle client server communication.
The second project is a WHOIS client which shows how to interact with a RESTful API and how to create a command line utility in GO.
The third and main project is a multi application system which analyze Twitter data streams to count specific tags, using a MongoDB as storage solution and a messaging system to decouple the applications and exposing a REST API for a web based client. With this project the author shows how to integrate a NoSQL database and a Queue Messaging system and how to create a REST API.
The book includes other projects with cover additional topics like how to interact with the file system.
All projects and their code are well described and, again, it is something we can really use in our projects.
Highly suggested.

View all my reviews

Review: Learning IBM Bluemix

Learning IBM Bluemix
Learning IBM Bluemix by Sreelatha Sankaranarayanan

My rating: 3 of 5 stars

Updated post can be found on my new blog site.

Interesting introduction to the Bluemix world
This book is a showcase, with working examples, of what we can do with IBM Bluemix cloud environment and its integrated IBM and third party services.
The main focus is to show what can be done, not how it works. Most of the technical backgrounds are left to several links to external resources on the web.
First step is how to create an application using Bluemix templates (“boilerplates”).
The following chapters are on how to integrate the application to the available services like security, SQL and NoSQL databases and IBM Watson functions, how to use the Bluemix development environment (git repository, continuous integration and deployment, test..) and how to monitor and tune application performances.
Other chapters are devoted to hybrid (cloud and on-premise) solutions and to mobile applications.
Most of the examples are based on Node.js or Java using IBM Liberty application server.
A couple of warnings:
– Bluemix IaaS (Infrastructure as-a-service) features like Docker and Open Stack virtual machines support are mentioned but not described. The book focus is on PaaS (Platform as-a-service) features, based on Pivotal’s Cloud Foundry solution.
– Bluexmix is a fast evolving environment so book screen shots and features lists can be easily obsoleted after few months
View all my reviews