Image Blog Your Next Cloud App Will Probably Suck
January 3, 2013

Unit Testing Cloud Applications in Java

Java Testing
Java Application Development

In this post, we'll introduce unit tests to less experienced developers and remind the more senior Java masters out there that it's still important to review the basics from time to time. Our goal is to help you learn why unit tests are important to the software development process, plus how to set up and run your own unit tests for cloud applications.

Are Unit Tests Necessary?

Believe it or not, unit testing is actually a controversial topic among Java developers. Some think that writing unit tests is a waste of time, while others consider them an essential part of the software development process, and the way to ensure that your new app doesn’t, well, suck because it wasn’t checked properly. And yet some developers are bored by the topic of Cloud application unit testing.

"Why are you even writing about that?" is something I heard recently from a developer friend, who had been using unit tests for so long that he considered them part of the "room" already for Java development.

Put simply, developers use unit tests as an internal control on the functionality and compatibility of their applications when changes to features, code or the environment happen.

Unit tests themselves are composed of programming code (just like the rest of the application), but they are not shipped along with the product. Instead, we use unit tests during development.

Solving Problems, Saving Time and Eliminating Waste with Unit Testing

Use your imagination for a minute to consider this common scenario for companies that haven't yet integrated unit testing methodologies into their software development process.

  • Stage 1: The Operations team is currently running your coolest application, SuperBlagTM v5.3, in production while the development team is busy preparing v5.4.
  • Stage 2: After two frantic months of development, the QA team (if it exists in the organization) gets the new version for testing.
  • Stage 3: The QA team, naturally, checks the new features of 5.4 (assuming that everything else works correctly).
  • Stage 4: After approval by QA, the new version 5.4 is deployed to production.

Sounds pretty reasonable, right? But how familiar does this next part sound? ....

A few days after releasing v5.4, users are surprised to find that what they want to do (and/or what they USED to do) completely fails. They are furious because this feature worked in version 5.3. The overworked QA team admits that they tested only new functionality for 5.4, and now the dev team is scrambling to discover the bug.

After some investigation, the development team realizes that some changes for the new version have affected more core parts of the application.

They fix the bug and inform QA that, actually, they really need to test EVERYTHING from the very beginning.

The result: users are unhappy and not trusting your app, QA is unhappy with the extra effort and development team is afraid of refactoring.

If we are lucky, the fix is made and a bug-free v5.3.1 reaches production. However there is the possibility that the fix breaks something else in another feature of SuperBlagTM that is found again by your unhappy users after a few more days. Thus we see this endless circle that can become a reality in really big enterprise applications.

This is what unit tests are attempting to solve -- if you can solve this problem by catching regressions in application code, then all the things that worked in the previous version should also work in the next.

“Hello World” in Cloud App Unit Testing

In Java there is much love for a highly popular unit testing framework called JUnit. Most Java IDEs (i.e. Eclipse, IntelliJ IDEA, NetBeans) have explicit support for JUnit, making it ideal for those of you who are interested in getting started with unit testing. For the sake of this example, let’s say that the "Enterprise Product" is an e-shop and we want to test the module that calculates the total weight of an order. Here is the sample code:

public class BasketWeightCalculator {

	private int totalWeight = 0;

	public void addItem( int itemWeight) //Assume weight is always an integer number
		totalWeight = totalWeight + itemWeight;

	public int getTotalWeight() {
		return totalWeight;


The code just adds the weight of any new item to the existing weight of the basket. Now it's time to write the unit test.

The suggested way of writing unit tests is to do it gradually. You start with very basic assumptions and continue to more advanced ones. The first thing to test, of course, is a simple case of using just one or two items.

We expect the weight of the basket to be just the sum. But let’s think of a more advanced (yet still simple) test - why don’t we make sure that the order of the items does not matter:

import static org.junit.Assert.assertEquals;
import org.junit.Test;

public class BasketWeightTest {

	public void oneItem() {
		BasketWeightCalculator weightCalculator = new BasketWeightCalculator();

		assertEquals("Expected 5",5 ,weightCalculator.getTotalWeight());

	public void twoItems() {
		BasketWeightCalculator weightCalculator = new BasketWeightCalculator();

		assertEquals("Expected 18",18 ,weightCalculator.getTotalWeight());

	public void orderDoesNotMatter() {
		BasketWeightCalculator weightCalculator1 = new BasketWeightCalculator();

		BasketWeightCalculator weightCalculator2 = new BasketWeightCalculator();

		assertEquals("Expected 18",18 ,weightCalculator1.getTotalWeight());
		assertEquals("Expected 18",18 ,weightCalculator2.getTotalWeight());

This unit test is normal Java code, but there are three points here to consider:

  • The name of the class is "name of the class being tested" + “Test” This is not a strict requirement but it is a good convention followed by several tools.
  • The test methods are annotated with the @Test annotation, but the test methods themselves can have any name.
  • The most crucial step is the assert Method, found at the end of each test method. This indicates whether the test fails or not.

There are several assert methods for each basic Java type but their syntax is similar. The second argument is the expected result, while the final argument is the actual result. If those two match, then the test is a success. If not the test fails.

Now you can save this file in your source folder and since we are using Eclipse for this example, you can right-click on it and select "run as unit test". If everything goes ok you will see the infamous green bars!

Congratulations! Everything seems to be in order, and your code is matching expectations.

Feature-Driven Unit Testing

One of the most important requirements for unit tests is that they should always reflect the current state of the code. Unit tests should be considered from the end user perspective and driven by the features required by your customers.

Imagine, for example, your squash buddy from Business Analysis comes over and says that because this method calculates weights, it should never return negative numbers. That seems right!

Therefore, the specifications of the e-shop are updated, and developers must also update the code. But since we are running unit tests, let’s first write the test before the actual code is implemented (this is also known as test driven development). Here is the test:

/** Feature request BWC-356. Weight can never be negative */ 
public void neverNegativeWeigth() {
	BasketWeightCalculator weightCalculator = new BasketWeightCalculator();

	assertEquals("Expected 0",0 ,weightCalculator.getTotalWeight());

If you run it again with Eclipse, not only the test will fail, but you will also see why it failed.

This is natural because the implementation code is missing. So, let’s add to the class the following code:

public void addItem( int itemWeight)
	totalWeight = totalWeight + itemWeight;

	/* Feature request BWC-356. Weight can * never be negative */  
        if(totalWeight < 0) { totalWeight = 0; }

And now you can sit back and watch your test pass!

Unit Tests as Warning Signals

In this imaginary scenario, the business analyst knew that the e-shop also sells virtual goods. For logistical reasons, the weight CAN also be zero. This is defined in the specifications.

Let's jump forward a year. Sara, a new developer, comes into the team and begins working on the shipping module of the e-shop using a complex algorithm for a new country. Her algorithm sometimes doesn't work because "weight = 0". The deadline is near.

In order to solve this last minute problem she finds the BasketWeightCalculator class and thinking that nothing will break, she changes it to:

	 * Feature request BWC-356. Weight can
	 * never be negative
	if(totalWeight < 0)
		totalWeight = 1;

This small change can have many side effects. A cursory glance might lead you to believe that this is logical, since weight can never be zero in real life. But there is little time to actually check the feature request marked BWC-356, and these specifications might not even be present in the original state.

So Sara happily commits the code, and the new module works perfectly. The updated version goes into production, but then two days later the shipping company calls the e-shop company with alarming news: Their system is down because it has been overwhelmed by shipping orders for downloadable goods (which of course they cannot ship) with “Weight 1”.

Actually, this outcome should not have happened in the first place. Even if Sara had no time to actually check the specs, she should have been instructed to run all the unit tests before committing her code (a very good practice you should also embrace). If this had occurred, then the tests would have failed, especially the test that checks if weight = 0.

Thus the Big Red Bar in the unit test results should act as a warning signal to any developer that something is wrong. Small changes might not be as trivial as originally thought. As we will see in a later post of the series, unit tests should also execute automatically in the build server.

Closing Remarks....

We hope that you have enjoyed learning a little about the usefulness of unit tests and why they are crucial for ensuring that you can deliver quality apps to your end users. Using our examples provided, you can make your own unit tests to make sure your code meets expectations, and follow these simple steps to catch regressions when shipping code into production.

In future articles, we'll look to cover things like what parts you need to select for testing in a big enterprise application, what is a good unit testing code coverage and some advanced JUnit techniques.

Unit testing is important, but it's good to be proactive with your code. Learn more about how processes for unit testing and mock testing in this blog post.

Save Time on Development

See how your team can save an average of 150 hours a year with a free, 10-day XRebel trial.

Try JRebel for Free