, ,

I have met many developers who refer to tests as “Unit Tests” when they are actually integration tests. In service layers, I’ve seen tests referred as unit tests, but written with dependencies on the actual service, such as a database, web service, or some message server. Those are part of integration testing. Even if you’re just using the Spring Context to auto-wire dependencies, your test is an integration test. Rather than using the real services, you can use Mockito mocks and spies to keep your tests unit tests and avoid the overhead of running integration tests.

This is not to say Integration tests are bad. There is certainly a role for integration tests. They are a necessity.

But compared to unit tests, integration tests are sloooowwwww. Very slow. Your typical unit test will execute in a fraction of a second. Even complex unit tests on obsolete hardware will still complete sub-second.

Integration tests, on the otherhand take several seconds to execute. It takes time to start the Spring Context. It takes time to start a H2 in memory database. It takes time to establish a database connection.

While this may not seem much, it becomes exponential on a large project. As you add more and more tests, the length of your build becomes longer and longer.

No developer wants to break the build. So we run all the tests to be sure. As we code, we’ll be running the full suite of tests multiple times a day. For your own productivity, the suite of tests needs to run quickly.

If you’re writing Integration tests where a unit test would suffice, you’re not only impacting your own personal productivity. You’re impacting the productivity of the whole team.

On a recent client engagement, the development team was very diligent about writing tests. Which is good. But, the team favored writing Integration tests. Frequently, integration tests were used where a Unit test could have been used. The build was getting slower and slower. Because of this, the team started refactoring their tests to use Mockito mocks and spies to avoid the need for integration tests.

They were still testing the same objectives. But Mockito was being used to fill in for the dependency driving the need for the integration test.

For example, Spring Boot makes it easy to test using a H2 in memory database using JPA and repositories supplied by Spring Data JPA.

But why not use Mockito to provide a mock for your Spring Data JPA repository?

Unit tests should be atomic, lightweight, and fast that are done as isolated units. Additionally, unit tests in Spring should not bring up a Spring Context. I have written about the different types of tests in my earlier Testing Software post.

I have already written a series of posts on JUnit and a post on Testing Spring MVC With Spring Boot 1.4: Part 1. In the latter, I discussed unit testing controllers in a Spring MVC application.

I feel the majority of your tests should be unit tests, not integration tests. If you’re writing your code following the SOLID Principles of OOP, your code is already well structured to accept Mockito mocks.

In this post, I’ll explain how to use Mockito to test the service layer of a Spring Boot MVC application. If Mockito is new for you, I suggest reading my Mocking in Unit Tests With Mockito post first.

Using Mockito Mocks and SpiesMockito Mocks vs Spies

In unit test, a test double is a replacement of a dependent component (collaborator) of the object under test. The test double does not have to behave exactly as the collaborator. The purpose is to mimic the collaborator to make the object under test think that it is actually using the collaborator.

Based on the role played during testing, there can be different types of test doubles. In this post we’re going to look at mocks and spies.

There are some other types of test doubles, such as dummy objects, fake objects, and stubs. If you’re using Spock, one of my favorite tricks was to cast a map of closures in as a test double. (One of the many fun things you can do with Groovy!)

What makes a mock object different from the others is that it has behavior verification. Which means the mock object verifies that it (the mock object) is being used correctly by the object under test. If the verification succeeds, you can conclude the object under test will correctly use the real collaborator.

Spies on the other hand, provides a way to spy on a real object. With a spy, you can call all the real underlying methods of the object while still tracking every interaction, just as you would with a mock.

Things get a bit different for Mockito mocks vs spies. A Mockito mock allows us to stub a method call. Which meams we can stub a method to return a specific object. For example, we can mock a Spring Data JPA repository in a service class to stub a getProduct() method of the repository to return a Product object. To run the test, we don’t need the database to be up and running – a pure unit test.

A Mockito spy is a partial mock. We can mock a part of the object by stubbing few methods, while real method invocations will be used for the other. By saying so, we can conclude that calling a method on a spy will invoke the actual method, unless we explicitly stub the method, and therefore the term partial mock.

Let’s look mocks vs spies in action, with a Spring Boot MVC application.

The Application Under Test

Our application contains a single Product JPA entity. CRUD operations are performed on the entity by ProductRepository using a CrudRepository supplied by Spring Data JPA. If you look at the code, you will see all we did was extend the Spring Data JPA CrudRepository to create our ProductRepository. Under the hood, Spring Data JPA provides implementations to manage entities for most common operations, such as saving an entity, updating it, deleting it, or finding it by id.

The service layer is developed following the SOLID design principles. We used the “Code to an Interface” technique, while leveraging the benefits of dependency injection. We have a ProductService interface and a ProductServiceImpl implementation. It is this ProductServiceImpl class that we will unit test.

Here is the code of ProductServiceImpl .

ProductServiceImpl.java

In the ProductServiceImpl class, you can see that ProductRepository is @Autowired in. The repository is used to perform CRUD operations. – a mock candidate to test ProductServiceImpl.

Testing with Mockito Mocks

Coming to the testing part, let’s take up the getProductById() method of ProductServiceImpl. To unit test the functionality of this method, we need to mock the external Product and ProductRepository objects. We can do it by either using the Mockito’s mock() method or through the @Mockito annotation. We will use the latter option since it is convenient when you have a lot of mocks to inject.

Once we declare a mock` with the @Mockito annotation, we also need to initialize it. Mock initialization happens before each test method. We have two options – using the JUnit test runner, MockitoJUnitRunner or MockitoAnnotations.initMocks() . Both are equivalent solutions.

Finally, you need to provide the mocks to the object under test. You can do it by calling the setProductRepository() method of ProductServiceImpl or by using the @InjectMocks annotation.

The following code creates the Mockito mocks, and sets them on the object under test.

Note: Since we are using the Spring Boot Test starter dependency, Mockito core automatically is pulled into our project. Therefore no extra dependency declaration is required in our Maven POM.

Once our mocks are ready, we can start stubbing methods on the mock. Stubbing means simulating the behavior of a mock object’s method. We can stub a method on the ProductRepository mock object by setting up an expectation on the method invocation.

For example, we can stub the findOne() method of the ProductRepository mock to return a Product when called. We then call the method whose functionality we want to test, followed by an assertion, like this.

This approach can be used to test the other methods of ProductServiceImpl, leaving aside deleteProduct() that has void as the return type.

To test the deleteProduct(), we will stub it to do nothing, then call deleteProduct(), and finally assert that the delete() method has indeed been called.

Here is the complete test code for using Mockito mocks:

ProductServiceImplMockTest.java

Note: An alternative to doNothing() for stubbing a void method is to use doReturn(null).

Testing with Mockito Spies

We have tested our ProductServiceImpl with mocks. So why do we need spies at all? Actually, we don’t need one in this use case.

Outside Mockito, partial mocks were present for a long time to allow mocking only part (few methods) of an object. But, partial mocks were considered as code smells. Primarily because if you need to partially mock a class while ignoring the rest of its behavior, then this class is violating the Single Responsibility Principle, since the code was likely doing more than one thing.

Until Mockito 1.8, Mockito spies were not producing real partial mocks. However, after many debates & discussions, and after finding a valid use case for partial mock, support for partial mock was added to Mockito 1.8.

You can partially mock objects using spies and the callRealMethod() method. What it means is without stubbing a method, you can now call the underlying real method of a mock, like this.

Be careful that the real implementation is ‘safe’ when using thenCallRealMethod(). The actual implementation needs be able to run in the context of your test.

Another approach for partial mocking is to use a spy. As I mentioned earlier, all method calls on a spy are real calls to the underlying method, unless stubbed. So, you can also use a Mockito spy to partially mock few stubbed methods.

Here is the code provide a Mockito spy for our ProductServiceImpl .

ProductServiceImplSpyTest.java

In this test class, notice we used MockitoJUnitRunner instead of MockitoAnnotations.initMocks() for our annotations.

For the first test, we expected NullPointerException because the getProductById() call on the spy will invoke the actual getProductById() method of ProductServiceImpl, and our repository implementations are not created yet.

In the second test, we are not expecting any exception, as we are stubbing the save() method of ProductRepository.

The second and third methods are the relevant use cases of a spy in the context of our application– verifying method invocations.

Conclusion

In Spring Boot applications, by using Mockito, you replace the @Autowired components in the class you want to test with mock objects. In addition to unit test the service layer, you will be unit testing controllers by injecting mock services. To unit test the DAO layer, you will mock the database APIs. The list is endless – It depends on the type of application you are working on and the object under test. If your following the Dependency Inversion Principle and using Dependency Injection, mocking becomes easy.

For partial mocking, use it to test 3rd party APIs and legacy code. You won’t require partial mocks for new, test-driven, and well-designed code that follows the Single Responsibility Principle. Another problem is that when() style stubbing cannot be used on spies. Also, given a choice between thenCallRealMethod on mock and spy, use the former as it is lightweight. Using thenCallRealMethod on mock does not create the actual object instance but bare-bones shell instance of the Class to track interactions. However, if you use spy, you create an object instance. As regard spy, use it if you only if you want to modify the behavior of small chunk of API and then rely mostly on actual method calls.

The code for this post is available for download here.

1
Share
, ,

Unit tests should be small tests (atomic), lightweight, and fast. However, an object under test might have dependencies on other objects. It might need to interact with a database, communicate with a mail server, or talk to a web service or a message queue. All these services might not be available during unit testing. Even if they are available, unit testing the object under test along with its dependencies can take unacceptable amount of time. What if?

  • The web service is not reachable.
  • The database is down for maintenance.
  • The message queue is heavy and slow.

These all defeat the whole purpose of unit tests being atomic, lightweight, and fast. We want unit tests to execute in a few milliseconds. If the unit tests are slow, your builds become slow, which affects the productivity of your development team. The solution is to use mocking, a way to provide test doubles for your classes being tested.

If you’ve been following the SOLID Principles of Object Oriented Programming, and using the Spring Framework for Dependency Injection, mocking becomes a natural solution for unit testing. You don’t really need a database connection. You just need an object that returns the expected result. If you’ve written tightly coupled code, you will have a difficult time using mocks. I’ve seen plenty of legacy code which could not be unit tested because it was so tightly coupled to other dependent objects. This untestable code did not follow the SOLID Principles of Object Oriented Programming, nor did it utilize Dependency Injection.

Mock Objects: Introduction

In unit test, a test double is a replacement of a dependent component (collaborator) of the object under test. A test double provides the same interface as of the collaborator. It may not be the complete interface, but for the functionality required for the test. Also, the test double does not have to behave exactly as the collaborator. The purpose is to mimic the collaborator to make the object under test think that it is actually using the collaborator.

Based on the role played during testing, there can be different types of test doubles, and mock object is one of them. Some other types are dummy object, fake object, and stub.

What makes a mock object different from the others is that it uses behavior verification. It means that the mock object verifies that it (the mock object) is being used correctly by the object under test. If the verification succeeds, it can be considered that the object under test will correctly use the real collaborator.

Free Spring Tutorial
Check out my FREE Introduction to Spring course!

The Test Scenario

For the test scenario, consider a product ordering service. A client interacts with a DAO to fulfill a product ordering process.

We will start with the Product domain object and the DAO interface, ProductDao.

Product.java

ProductDao.java

For the purpose of the example, I kept the Product class empty. But in real applications, it will typically be an entity with states having corresponding getter and setter methods, along with any implemented behaviors.

In the ProductDao interface, we declared two methods:

  • The getAvailableProducts() method returns the number of available quantity of a Product passed to it.
  • The orderProduct() places an order for a product.

The ProductService class that we will write next is what we are interested on the object under test.

ProductService.java

The ProductService class above is composed of ProductDao, which is initialized through a setter method. In the buy() method, we called getAvailableProducts() of ProductDao to check if sufficient quantity of the specified product is available. If not, an exception of type InsufficientProductsException is thrown. If sufficient quantity is available, we called the orderProduct() method of ProductDao.

What we now need is to unit test ProductService. But as you can see, ProductService is composed of ProductDao, whose implementations we don’t have yet. It can be a Spring Data JPA implementation retrieving data from a remote database, or an implementation that communicates with a Web service hosting a cloud-based repository – We don’t know. Even if we have an implementation, we will use it later during integration testing, one of the software testing type I wrote earlier on. But now, we are not interested on any external implementations in this unit test.

In unit tests, we should not to be bothered what the implementation is doing. What we want is to test that our ProductService is behaving as expected and that it is able to correctly use its collaborators. For that, we will mock ProductDao and Product using Mockito.

The ProductService class also throws a custom exception, InsufficientProductsException. The code of the exception class is this.

InsufficientProductsException.java

Using Mockito

Mockito is a mocking framework for unit tests written in Java. It is an open source framework available at github. You can use Mockito with JUnit to create and use mock objects during unit testing. To start using Mockito, download the JAR file and place it in your project class. If you are using Maven, you need to add its dependency in the pom.xml file, as shown below.

pom.xml

Once you have set up the required dependencies, you can start using Mockito. But, before we start any unit tests with mocks, let’s have a quick overview of the key mocking concepts.

Mock Object Creation

For our example, it’s apparent that we need to mock ProductDao and Product. The simplest way is through calls to the mock() method of the Mockito class. The nice thing about Mockito is that it allows creating mock objects of both interfaces and classes without forcing any explicit declarations.

MockCreationTest.java

An alternative way is to use the @Mock annotation. When you use it, you will need to initialize the mocks with a call to MockitoAnnotations.initMocks(this) or specify MockitoJUnitRunner as the JUnit test runner as @RunWith(MockitoJUnitRunner.class).

MockCreationAnnotationTest.java

Stubbing

Stubbing means simulating the behavior of a mock object’s method. We can stub a method on a mock object by setting up an expectation on the method invocation. For example, we can stub the getAvailableProducts() method of the ProductDao mock to return a specific value when the method is called.

In Line 4 of the code above, we are stubbing getAvailableProducts(product) of ProductDao to return 30. The when() method represents the trigger to start the stubbing and thenReturn() represents the action of the trigger – which in the example code is to return the value 30. In Line 5 with an assertion, we confirmed that the stubbing performed as expected.

Verifying

Our objective is to test ProductService, and unitl now we only mocked Product and ProductDao and stubbed getAvailableProducts() of ProductDao.

We now want to verify the behavior of the buy() method of ProductService. First, we want to verify whether it’s calling the orderProduct() of ProductDao with the required set of parameters.

In Line 6 we called the buy() method of ProductService that is under test. In Line 7, we verified that the orderProduct() method of the ProductDao mock get’s invoked with the expected set of parameters (that we passed to buy()).

Our test passed. But, not complete yet. We also want to verify:

  • Number of invocations done on a method: The buy() method invokes getAvailableProduct() at least once.
  • Sequence of Invocation: The buy() method first invokes getAvailableProduct(), and then orderProduct().
  • Exception verification: The buy() method fails with InsufficientProductsException if order quantity passed to it is more than the available quantity returned by getAvailableProduct().
  • Behavior during exception: The buy() method doesn’t invokes orderProduct() when InsufficientProductsException is thrown.

Here is the complete test code.

ProductServiceTest.java

I have already explained the initial code of the test class above. So we will start with Line 36 – Line 38 where we used the inOrder() method to verify the order of method invocation that the buy() method makes on ProductDao.

Then we wrote a purchaseWithInsufficientAvailableQuantity() test method to check whether an InsufficientProductsException gets thrown, as expected, when an order with quantity more than the available quantity is made. We also verified in Line 54 that if InsufficientProductsException gets thrown, the orderProduct() method is not invoked.

The output of the test is this.

Mockito Mocks vs Mockito Spies

In testing Spring Boot applications sometimes you need to access the real component. This is where Mockito Spies come into the picture. If you’d like to learn more about using Mockito Spies, check out this post.

Summary

Mocking in unit testing is extensively used in Enterprise Application Development with Spring. By using Mockito, you can replace the @Autowired components in the class you want to test with mock objects. You will be unit testing controllers by injecting mock services. You will also be setting up services to use mock DAOs to unit test the service layer. To unit test the DAO layer, you will mock the database APIs. The list is endless – It depends on the type of application you are working on and the object under test. If you’re following the Dependency Inversion Principle and using Dependency Injection, mocking becomes easy.

The Mockito library is a very large and mature mocking library. It is very popular to use for mocking objects in unit tests. Mockito is popular because it is easy to use, and very versatile. I wrote this post as just an introduction to mocking and Mockito. Checkout the official Mockito documentation to learn about all the capabilities of Mockito.

Free Spring Tutorial
Check out my FREE Introduction to Spring course!
6
Share
, ,

In this series on unit testing with JUnit, we learned several unit testing aspects and how to implement them with JUnit. We can summarize the series till now as:

  • Part 1: Creating a basic unit test both using Maven and IntelliJ
  • Part 2: Using assertions and annotations
  • Part 3: Using assertThat with Hamcrest matchers

In this post, we will learn about parameterized tests and theories.

JUnit Parameterized Tests

While testing, it’s common to execute a series of tests which differ only by input values and expected results. As an example, if you are testing a method that validates email IDs, you should test it with different email ID formats to check whether the validations are getting correctly done. But testing each email ID format separately, will result in duplicate or boilerplate code. It is better to abstract the email ID test into a single test method and provide it a list of all input values and expected results. JUnit supports this functionality through parameterized tests.

To see how parameterized test works, we’ll start with a class with two methods which we will put under test.

EmailIdUtility.java

The EmailIdUtility class above has two utility methods. The createEmailID() method accepts two String parameters and generates an email ID in a specific format. The format is simple – If you pass mark and doe as parameters to this method, it returns [email protected]. The second isValid() method accepts an email ID as a String, uses regular expression to validate it’s format, and returns the validation result.

We will first test the isValid() method with a parameterized test. JUnit runs a parameterized test with a special runner, Parameterized and we need to declare it with the @RuntWith annotation. In a parameterized test class, we declare instance variables corresponding to the number of inputs to the test and the output. As the isValid() method under test takes a single String parameter and returns a boolean, we declare two corresponding variables. For a parameterized test, we need to provide a constructor, which will initialize the variables. 

EmailIdValidatorTest.class

We also need to provide a public static method annotated with @Parameters annotation. This method will be used by the test runner to feed data into our tests.

The @Parameters annotated method above returns a collection of test data elements (which in turn are stored in an array). Test data elements are the different variations of the data, including the input as well as expected output needed by the test. The number of test data elements in each array must be the same with the number of parameters we declared in the constructor.

When the test runs, the runner instantiates the test class once for each set of parameters, passing the parameters to the constructor that we wrote. The constructor then initializes the instance variables we declared.

Notice the optional name attribute we wrote in the @Parameters annotation to identify the parameters being used in the test run. This attribute contains placeholders that are replaced at run time.

  • {index}: The current parameter index, starting from 0.
  • {0}, {1}, …: The first, second, and so on, parameter value. As an example, for the parameter {“[email protected]”, true}, then {0} = [email protected] and {1} = true.

Finally, we write the test method annotated with @Test. The complete code of the parameterized test is this.

EmailIdValidatorTest.java

The output on running the parameterized test in IntelliJ is this.

Parameterized Test Output

JUnit Theories

In a parameterized test, the test data elements are statically defined and you as the programmer are responsible for figuring out what data is needed for a particular range of tests. At times, you will likely want to make tests more generalized. Say, instead of testing for specific values, you might require to test for some wider range of acceptable input values. For this scenario, JUnit provides theories.

A theory is a special test method that a special JUnit runner (Theories) executes. To use the runner, annotate your test class with the @RunWith(Theories.class) annotation. The Theories runner executes a theory against several data inputs called data points. A theory is annotated with @Theory, but unlike normal @Test methods, a @Theory method has parameters. In order to fill these parameters with values, the Theories runner uses values of the data points having the same type.

There are two types of data points. You use them through the following two annotations:

  • @DataPoint: Annotates a field or method as a single data point. The value of the field or that the method returns will be used as a potential parameter for theories having the same type.
  • @DataPoints: Annotates an array or iterable-type field or method as a full array of data points. The values in the array or iterable will be used as potential parameters for theories having the same type. Use this annotation to avoid single data point fields cluttering your code.

Note: All data point fields and methods must be declared as public and static.

In the code example above, we annotated a String field with the @DataPoint annotation and a names() method that returns a String[] with the @DataPoints annotation.

Creating a JUnit Theory

Recall the createEmailID() method that we wrote earlier on this post – “The createEmailID() method accepts two String parameters and generates an email ID in a specific format.” A test theory that we can establish is “Provided stringA and stringB passed to createEmailID() are non-null, it will return an email ID containing both stringA and stringB ”. This is how we can represent the theory.

The testCreateEmailID() theory we wrote accepts two String parameters. At run time, the Theories runner will call testCreateEmailID() passing every possible combination of the data points we defined of type String. For example (mary,mary), (mary,first), (mary,second), and so on.

Assumptions

It’s very common for theories NOT to be valid for certain cases. You can exclude these from a test using assumptions, which basically means “don’t run this test if these conditions don’t apply“. In our theory, an assumption is that the parameters passed to the createEmailID() method under test are non-null values.

If an assumption fails, the data point is silently ignored. Programmatically, we add assumptions to theories through one of the many methods of the Assume class.
Here is our modified theory with assumptions.

In the code above, we used assumeNotNull because we assume that the parameters passed to createEmailID() are non-null values. Therefore, even if a null data point exists and the test runner passes it to our theory, the assumption will fail and the data point will be ignored.
The two assumeThat we wrote together performs exactly the same function as assumeNotNull. I have included them only for demonstrating the usage of assumeThat, which you can see is very similar to assertThat we covered in the earlier post.

The following is the complete code using a theory to test the createEmailID() method.

EmailIDCreatorTest.java

In the test class above, I have included null as a data point in the return statement of Line 23 for our assumptions and couple of System.out.println() statements to trace how parameters are passed to theories at run time.

Here is the output of the test in IntelliJ:
JUnit Theories Output

Also, here is the output I got while running the test with Maven for your review:

In the output above, notice that whenever a null value is being passed to the theory, the remaining part of the theory after assumeNotNull does not execute.

Summary

Parameterized tests in JUnit helps remove boiler plate test code and that saves time while writing test code. This is particularly useful during Enterprise Application Development with the Spring Framework. However, a common complaint is that when a parameterized test fails it’s very hard to see the parameters which caused it to fail. By properly naming the @Parameters annotation and great unit testing support that modern IDEs provide, such complains are quickly failing to hold grounds. Although theories are less commonly used, they are powerful instruments in any programmers test toolkit. Theories not only makes your tests more expressive but you will see how your test data becomes more independent of the code you’re testing. This will improve the quality of your code, since you’re more likely to hit edge cases, which you may have previously overlooked.

0
Share
, ,

In this series on unit testing with JUnit, we started with JUnit tests both using Maven and IntelliJ in the first part. In the second part, we learned about assertions, JUnit 4 annotations, and test suites. In this post, we will cover assertThat, a more expressive style of assertion that uses Hamcrest matchers.

Assertions with assertThat

The classic JUnit assertions, such as assertEquals, assertTrue, and so on are simple to understand and use. But, by using assertThat with Hamcrest matchers, It’s easy to make dramatic improvements to your tests. Hamcrest is a framework that provides support for Java unit testing. Hamcrest contains self-contained classes, called matchers with static methods designed to be used with JUnit assertThat.

What you can do with the classic assertions, you can also do with assertThat, but more fluently, and make tests more readable. For example, take a look at the following assertions:

As it is relevant, the second assertion is more readable. If you read out, the second assertion reads more like a sentence – “Assert that actual is not equal to expected”.

Beside test readability, readability of test failures is another highlight of assertThat, as shown in the following figure.

JUnit Assertion Failure Messages for assertFalse and assertThat

As you can see, the second assertion failure message of assertThat is far more explanatory as compared to assertFalse. It was because we used a core Hamcrest matcher.

Core Matchers

When you write an assertThat method, you pass two parameters to it. The first is the actual result, typically the value/object returned by the method under test. The second parameter is a matcher obtained from a call to a matcher method. The matcher is an object that matches the test rule. To see how it works, we will write a class with few methods that we will test.

MatchersDemo.java

In the class above, we wrote a toConcatedUpperCase() method that concatenates two strings passed as parameters, converts the result to uppercase, and returns it. We then wrote a floatingPointMultiplication() method that returns the product of two double values passed to it. We also wrote the addStringToCollection() and getStringCollection() that adds a string to a Set collection and returns the Set respectively.

We will next write a test class with few test methods.

MatchersDemoTest.java

In the test class above, we started with a static import of the Hamcrest core matcher, in Line 6 . We then used the @Before annotation to instantiate the MatchersDemo class. Recall from the previous post that the @Before annotated method will run before each @Test method in the class. Then, we wrote the assertions:

  • Line 18: We wrote an assertThat with the is method containing the equalTo method. We can read it as-“assert that actual (the value that toConcatedUpperCase() method returns) is equal to expected (HELLOWORLD). Although not necessary, many programmers like to use is and other matcher methods together because it makes assertions more readable. This is the very reason for the existence of is and being referred as decorator: to decorate other matchers.
  • Line 24: We used startsWith to assert that the actual string starts with the expected value, HELLO.
  • Line 31: We used containsString to test that the actual string contains the expected value WORLD.
  • Line 37: We wrote an assertThat with allOf, and things get interesting here. allOf takes multiple matcher methods and returns a matcher. This matcher test if the actual result matches all the specified matchers- think about the Java short circuit && operator. So, in a single assertion, we asserted that the actual result is not a null value, is an instance of the String class, and starts with and contains HELLO. The corresponding matcher method, that works like the Java short circuit || operator is anyOf.

When we run the test class above, all the test passes. But, the core matchers we used are only a subset of the wide range of Hamcrest matchers. There are additional matchers for specific test requirements, such as testing collections, numbers, text comparison, and so on. The aditional matchers are not part of JUnit, and to use them, we need to seperately download the Hamcrest matcher library and point the project classpath to it. If you are using Maven, add the following dependency to the pom.xml file.

Collection Matchers

Collections often have more complex testing needs. For example testing the size of a collection, testing for one or more elements in a collection, their ordering, etc. The Hamcrest collection matchers are designed to support the needs of testing collections in unit tests.
Let’s write a new test class and use the Hamcrest collection matchers.

CollectionMatchersTest

In the test class above, we initialized the Set collection of MatchersDemo with few strings in a @Before method. Then, we wrote the following assertions:

  • Line 23: We wrote a assertThat with hasSize to test the size of the collection.
  • Line 32: We used hasItems to test for multiple items in the collection. To test for a single item, you can use hasItem.
  • Line 41: We used containsInAnyOrder to test that all items in the collection match the expected items, in any order. If you want to test for all items in the same order, use the stricter contains.

Number Matchers

I particularly find the Hamcrest number matchers useful to test floating point calculations that provide accurate approximations, but not exact results. The assertion assertThat(2.32 * 3, equalTo(6.96)); will fail because the actual result is not what we expect (6.96). By, looking at the failure message we will understand the reason.

As you can notice, the actual value is different from what we expected. To test for such floating point calculations, there is a closeTo matcher method that we will cover now.

NumberMatchersTest

In Line 20 of the test class above, we used closeTo to test for the result of the floatingPointMultiplication() method under test. The closeTo method matches if an examined double value is equal to the first parameter value, within a range of +/- error specified by the second parameter. We also wrote an assertThat with greaterThan in Line 26 to check if the actual value returned by the method under test is greater than the specified value 6.0.

Some other number matcher methods are greaterThanOrEqualTo, lessThan, and lessThanOrEqualTo. As their names are self-explanatory, I won’t explain them further.

Text Comparison Matchers

We did some text comparisons with the core matchers on the toConcatedUpperCase() method earlier in this post. But, for more flexibility, let’s look at some specific text comparison matchers.

TextComparisionMatchersTest.java

In Line 21 and Line 27 we used equalToIgnoringCase and equalToIgnoringWhiteSpace to test for string equality while ignoring casing and white spaces respectively. In Line 33 we used stringContainsInOrder to test that the actual result contains the specified strings in the same sequence.

The Hamcrest matchers library is big. In this post we looked at few of them. But more importantly, we learned how unit tests are done the real way – Hamcrest matchers.

Summary

As you saw, JUnit’s assertThat combined with Hamcrest matchers has much better functionality. But by saying so, the old assert methods are here to stay. If you are running the old assert methods present in existing test code, you may continue doing so. But, if you plan to write new test code, consider using the Hamcrest matchers. They are more readable – as the JUnit release note says “This syntax allows you to think in terms of subject, verb, object– assert that x is 3”. Also, you will realize the full benefits when your test fails during complex testing. The detailed failure message will point you in the right direction at a very less, or no time at all.

During unit testing enterprise application code using the Spring Framework, you can unleash the potentials of the Hamcrest matchers. Beside the regular assertions, you can use the Hamcrest bean matchers to test properties of Spring beans. You can also use matchers to test whether a view name contains a specific string in Spring MVC, test responses from mock objects. You’ll find the versatility of the Hamcrest matchers very beneficial when writing unit tests in JUnit.

1
Share
, ,

In the first part of the series on unit testing with JUnit, we looked at creating unit tests both using Maven and IntelliJ. In this post, we will look at some core unit testing concepts and apply those using JUnit constructs. We will learn about assertions, JUnit 4 annotations, and test suites.

JUnit Assertions

Assertions, or simply asserts provide programmers a way to validate the intended behavior of code. For example, through an assertion you can check whether a method returns the expected value for a given set of parameters or a method correctly sets up some instance or class variables. When you run the test, the assertion executes. If the method under test behaves exactly as you specified in the assertion, your test passes. Otherwise, an AssertionError is thrown.

JUnit provides support for assertions through a set of assert methods in the org.junit.Assert class. Before we start using them, let’s have a quick overview of the Arrange, Act, Assert (AAA) pattern. This pattern is the recommended way to write unit test methods where you divide a method into three sections, each with a specific purpose:

  • Arrange: Initialize objects and set up input data for the method under test.
  • Act: Invoke the method under test passing the arranged parameters.
  • Assert: Verify that the method under test behaves as expected. This is where you write an assertion method.

Here is a Java class we will be writing some JUnit unit tests to test.

EmployeeEmail.java

In the EmployeeEmail class above, we wrote an addEmployeeEmailId() method that first checks whether an email ID is in valid format, and then adds it to a Map implementation. The isValidEmailId() method performs the email validation using a regular expression. We also wrote a getEmployeeEmailId() method to return an email ID from the Map, given a key.

To test the EmployeeEmail class, we will create a test class, EmployeeEmailTest and add test methods to it. Here, remember that the number of test methods to add and what they should do depends on the behavior of the EmployeeEmail class under test – not on the number of methods in it.

To start with, we will test that the getEmployeeEmailId() method returns true for a valid email ID and false for an invalid one with two test methods.

In both the test methods above, we separated the test code into the AAA sections. In the first test method, we used the assertTrue() method as we expect isValidEmailId() to return true for the email ID, [email protected]. We also want to test that isValidEmailId() returns false for an invalid email ID. For that, we wrote the second test method and used assertFalse().

Couple of things to observe here. In both the assertion methods, we passed a String parameter as the identifying message for an assertion error. It’s common for programmers to set this message to describe the condition that should be met. Instead, to be meaningful, this message should describe what’s wrong if the condition isn’t met.

Also, you might be thinking “Why two separate test methods instead of a single method with both the assert methods?” Having multiple assert methods in a single test method will not cause any errors in tests, and you will frequently encounter such test methods. But a good rule to follow is: “Proper unit tests should fail for exactly one reason”, which sounds similar to the Single Responsibility Principle.  In a failed test method having multiple assertions, more effort is required to determine which assertion failed. Also, it is not guaranteed that all of the assertions took place. For an unchecked exception, the assertions after the exception will not execute and JUnit proceeds to the next test method. Therefore, it is generally a best practice to use one assertion per test method.

With the basics in place, let’s write the complete test class and use the following assertions:

  • assertEquals() and assertNotEquals(): Tests whether two primitives/objects are equal or not. In addition to the string message passed as the first parameter, these methods accept the expected value as the second parameter and the actual value as the third parameter- an important ordering commonly misused.
  • assertNull() and assertNotNull(): Tests whether an object is null or not null.
  • assertSame() and assertNotSame(): Tests whether two object references point to the same object or don’t.

EmployeeEmailTest.java

In the EmployeeEmailTest class above:

  • Line 38: We used assertEquals() to test the collection size after adding two elements to it through addEmployeeEmailId().
  • Line 50: We used assertNotEquals() to test that the collection does not allow duplicate keys added through addEmployeeEmailId().
  • Line 62: We used assertNotNull() to test that getEmployeeEmailId() does not return null for an email ID present in the collection.
  • Line 74: We used assertNull() to test that getEmployeeEmailId() returns null for an email ID not present in the collection.
  • Line 89: We used assertSame() to test that two collection references point to the same collection object after assigning one to the other through the = operator.
  • Line 103: We used assertNotSame() to test that two collection references are not pointing to the same object.

When we run the test in IntelliJ, the output is:
Output in IntelliJ

As you can see from the output, all the tests passed as expected.

Note: The order in which JUnit executes test methods is not guaranteed, so don’t count on it.

If you go back and look into the test class, you will notice several lines of code in the Arrange part being repeated across the test methods. Ideally, they should be in a single place and get executed before each test. We can achieve this through the use of JUnit annotations, which we will look into next.

JUnit Annotations

You can use JUnit Annotations, introduced in JUnit 4, to mark and configure test methods. We have already used the @Test annotation to mark public void methods as test methods. When JUnit encounters a method annotated with @Test, it constructs a new instance of the class, and then invokes the method. We can optionally provide a timeout parameter to @Test to specify a time measured in milliseconds. If the test method takes longer to execute than the specified time, the test fails. This is particularly useful when you test against performance in terms of time. This code marks a method as a test method and sets the timeout to 100 milliseconds.

Another important use of the @Test annotation is to test for exceptions. Suppose for a condition, a code throws an exception. We can use the @Test annotation to test whether the code indeed throws the exception when the condition is met. This code checks whether the getEmployeeEmailId() method throws an exception of type IllegalArgumentException when a non-String value is passed to it.

In addition to the @Test annotation, the other annotations are:

  • @Before: Causes a method to run before each test method of the class. You typically use this annotation to allocate resource, setup common initialization code, and load configuration files that the test methods require.
  • @After: Causes a method to run after each test method of the class. This method is guaranteed to run even if a @Before or @Test method throws an exception. Use this annotation to clean up initialization code and release any resource allocations done in @Before.
  • @BeforeClass: Causes a static method to run once and only once before any of the test methods in the class. This is useful in situations where you need to set up computationally expensive resources, say a server connection, a database, or even managing an embedded server for testing. As an example, instead of starting a server for each @Test method, start it once in a @BeforeClass method for all the tests in the class.
  • @AfterClass: Causes a static method to run once after all the test methods in the class completes. This method is guaranteed to run even if a @BeforeClass or @Test method throws an exception. Use this method to free one time resource initialization done in @BeforeClass.
  • @Ignore: Causes a test method to be ignored by JUnit. This can be useful when you have a complicated piece of code that is in transition, and you might want to temporarily disable some tests till that code is ready. Test runners of most IDEs report @Ignore tests as reminders during each test runs. This is essentially to mark tests as “there are things to be done”, which otherwise you might forget if you comment out the test method or remove the @Test annotation.

Here is an example of using all the JUnit annotations.

EmployeeEmailAnnotationsTest.java

The output on running the test in IntelliJ is:

JUnit Output in IntelliJ

JUnit Test Suites

If you have large numbers of test classes for different functional areas or modules, you can structure them into test suites. JUnit Test Suites are containers of test classes and gives you finer control over what order your test classes are executed in. JUnit provides org.junit.runners.Suite, a class that runs a group of test classes.
The code to create a test suite is:

EmployeeEmailTestSuite.java

In the test suite class above, we wrote two annotations: @RunWith and @SuiteClasses. The @RunWith annotation instructs JUnit to use the Suite runner class and @SuiteClasses specifies the classes and their order that the Suite runner class should run. The test suite class is itself empty and acts only as a placeholder for the annotations.

The output on executing the test suite in IntelliJ is.

JUnit test suite Output in IntelliJ

Summary

JUnit Assertions not only make your code stable but also force you to think differently and think through different scenarios, which ultimately helps you to become better programmers. By understanding the purpose of different assertions and using them properly, testing becomes effective. But the question is “How many asserts per test method?”. It all comes down to the complexity of the method under test. For a method with multiple conditional statements, asserting the outcome for each condition should be done, while for a method performing a simple string manipulation, a single assertion should do. When developing unit tests with JUnit, it is considered a best practice that each test method is testing a specific condition, which will often lead to one assert per test method. Its not uncommon for a method under test to be associated with multiple test methods.
One assertion I have not covered in this post is assertThat(). It’s an important JUnit assertion which I will cover it in my next post on JUnit.

Unit Testing with the Spring Framework

While doing Enterprise Application Development with the Spring Framework and unit testing your code, you will be using lots of assertions. In addition to asserting the regular method behaviors, you will assert whether Spring beans are injected as expected by the Spring application context, whether dependencies between Spring beans are correctly maintained, and so on. While creating those tests ensure that they run fast, especially when testing is integrated in the build cycle. You will keep building your application as you code, and so you obviously won’t want your build to wait for a long running test to complete. If you do have such long running tests, put them in a separate test suite.

0
Share
, ,

In the first part of this tutorial series on creating a web application using Spring Boot, I showed how to use Spring Initializr to create the Maven project we’re using in this example. In the second part of the tutorial series, I showed you how to configure Spring MVC and ThymeLeaf templates to display a basic web page via Tomcat. In this part of my Spring Boot tutorial series, we’ll setup the H2 database and Spring Data JPA. We will use these tools to persist data to the database in our Spring Boot Web Application.

Database Persistence with Spring Boot

Spring Boot comes with pre-configured options for relational databases. Like other things in Spring Boot, these are enabled by simply having the dependency on your classpath.

While all the interest in the media is around No-SQL databases, relational databases are time proven work horses. They are not going anywhere soon. If you’re doing enterprise application development with the Spring Framework, you’re probably going to be using a relational database.

Hibernate / JPA does a great job of abstracting the persistence layer. If you want to change from Oracle to DB2 or to MySQL, it is just a matter of changing the database drivers. The JPA mapping code you use on your domain POJOs doesn’t change. Your application code does not change.

NOTE – the above statement is 95% true. When changing databases with complex mappings, you’re going to hit minor edge cases here and there.

When developing Spring applications, it is very common to use a in memory database for your development, and then a real database installation for your testing and production environments. Oracle is a great database, but it’s also BIG and resource intensive. I’ve run Oracle on a laptop. It takes a lot of resources. Its a great database, but its not really meant to run from a laptop.

The persistence API in Java follows the Interface Segregation design principle of object oriented design. So, its easy to plug in a different persistence implementation. With Spring managing the dependency injection for us, it makes swapping databases in and out very easy.

What we are going to do in this tutorial is setup an in-memory database, configure a JPA entity, setup Hibernate to automatically create the database tables, and on startup add data to the database for our use and testing.

By doing this, each time we start our application, we have a newly created database, with known data populated into the database tables. It sounds like a lot of work, but it’s really not much. And it does not add very much to your startup time. With the speed of modern computers, even a complex set of tables and data is going to load in just a few seconds.

The advantage of doing this for you as the developer is you’re working against known data while you are doing your development. It also sets you up for being able to automate integration and functional tests with a continuous build server such as Jenkins.

Free Spring Tutorial
Click Here for my free Spring Course!

H2 Database

The H2 database is a popular database to use when developing Spring applications. H2 is written in Java and is easily runs as an embedded in-memory database. Because it is an embedded in memory database, it makes your build portable. Your build will run anywhere Maven will run.

If you used a database like Oracle or MySQL, now you’ve introduced an external dependency. Your build is no longer portable. If you wanted to do the build under Jekins on a build server, you’d need to install the database on that server or provide a configuration pointing to a database elsewhere.

By using the H2 database as an embedded in memory database, your build remains portable.

H2 Database and Spring Boot

Configuring the H2 database with Spring Boot is very easy. You just need to add the H2 dependency to your Maven Pom. Spring Boot will automatically create the database, setup all the database JDBC objects, and by default configure Hibernate in a create-drop mode. Thus, when Hibernate starts up, it will scan the JPA annotated classes and automatically generate and execute the SQL code needed to create the database tables.

pom.xml

By adding this dependency to your Maven POM, Spring Boot will automatically configure the H2 database.

H2 Database Console

H2 comes with a really cool web based database console you can use to query the database. This is very handy to use when developing with the H2 database and the Spring Framework. When developing the code for this post, I ran into a couple of “gotchas” with setting up the H2 Database Console with Spring Security. It inspired me to write a blog post about it. If you’re following this tutorial step by step, please complete the steps in this post now.

NOTE: When connecting, be sure your JDBC url is set to ‘jdbc:h2:mem:testdb’.

h2 database console

JPA Entities

JPA, which stands for Java Persistence API, is a Java standard. It’s important to remember JPA is just the API (Application Programming Interface) standard. Java itself does not ship with JPA included. For that, you need to include an JPA implementation. There’s number of open source and commercial JPA implementations available.

Free Spring Tutorial
Click here for my free Spring course!

Hibernate and Spring Boot

Hibernate is by far the most popular. When you include the Spring Data JPA dependency in your Maven POM, Hibernate is included by default. As typical with Spring Boot, Hibernate is setup and configured with sensible default properties.

pom.xml

The Spring Data JPA dependencies includes Hibernate. Spring Boot will automatically configure default Hibernate properties.

Example JPA Entity

In our example application, we’re going to use a product for a ecommerce website. I’ll cover JPA mappings in more detail in future posts. Its a subject that could easily be a tutorial series of its own. For now, we just need a product entity.

By convention, I like to put my entity classes in a package called ‘domain’. This is just my personal habit. Probably something I picked up from working so much with the Grails framework.

Product.java

Spring Data JPA

Using Spring Data JPA can save you a lot of time when interacting with the database. Spring Data JPA implements the Repository Pattern. This design pattern was originally defined by Eric Evans and Martin Fowler, in their book Domain Driven Design. This is one of those time test computer science books, over a decade old, still remains relevant today.

You don’t need to use Spring Data JPA for this type of project. But using Spring Data JPA will make your life as a developer easier. A common alternative to Spring Data JPA would be to use the widely accepted DAO pattern, The DAO pattern is very similar to the Repository Pattern. The advantage of using Spring Data JPA is that you’ll be writing a lot less code. Spring Data JPA works a lot like Spring Integration Gateways, where you define an interface, and Spring provides the implementation at run time.

Spring Data JPA CRUD Repository

The Spring Data JPA CRUD Repository is my favorite feature of Spring Data JPA. Similar to coding with a Spring Integration Gateway, you can just define an interface. Spring Data JPA uses generics and reflection to generate the concrete implementation of the interface we define.

Defining a repository for our Product domain class is as simple as defining a interface and extending the CrudRepository interface. You need to declare two classes in the generics for this interface. They are used for the domain class the repository is supporting, and the type of the id declared of the domain class.

For our Product domain class we can define a Spring Data JPA repository as follows.

ProductRepository.java

Integration Testing with Spring Data JPA and JUnit

Even though we are building a web application, we can test the persistence layer without creating a WAR file, and without deploying to Tomcat. We want to set up some integration tests to test our JPA mapping and interactions with the Spring Data JPA repository. To do this, we’re going to take advantage of the auto-configuration options available to us in Spring Boot. By doing this, there is a lot of boilerplate code we don’t need to write.

Spring Data JPA Repository Test Configuration

For our integration tests, we’re going to use a Spring Context to wire up beans to support our tests. If we were not using Spring Boot, we’d need to create a number of beans ourselves. Normally we would need to create:

  • The H2 data source
  • The Hibernate Entity Manager
  • A JPA Transaction Manager

But since we’re using Spring Boot, we don’t need to write code to create these beans. For the purposes of our integration tests for our Spring Data JPA repositories, we can complete our Java configuration with just annotations.

RepositoryConfiguration.java

While this is an empty Java class file, each of the annotations is very important.

  • @Configuration  tells the Spring Framework this is a Java configuration class.
  • @EnableAutoConfiguration tells Spring Boot to do its auto configuration magic. This is what has Spring Boot automatically create the Spring Beans with sensible defaults for our tests.
  • @EntityScan specifies the packages to look for JPA Entities.
  • @EnableJpaRepositories enables the auto configuration of Spring Data JPA.
  • @EnableTransactionManagement Enables Spring’s annotation driven transaction management

Through this configuration, we have everything we need to use the H2 database with Spring Data JPA in JUnit tests.

Spring Data JPA JUnit Integration Test

With our Spring Java configuration done, our JUnit integration test becomes very simple to write. If you’re new to writing JUnit Integration tests with the Spring Framework, checkout this post where I go into this subject much deeper than I am here. Or if you’re new to JUnit, you may wish to start here.

In this post, I am not going to go in depth with Spring Data JPA. This is fairly large and complex project in the Spring Framework. We’re going to use the CRUD repository from Spring Data JPA. CRUD stands for Create, Read, Update, Delete. Your basic persistence operations. Simply extending the Spring Data JPA’s CRUD Repository interface, as we did above, for the specified Entity we will get methods which will:

  • Save an entity
  • Find an entity based on its ID
  • Check if an entity exists based on its ID
  • Get a list of all entities
  • Get a count of all entities
  • Delete an entity
  • Delete all entities

I’ve written a simple integration test for the Spring Data JPA repository I defined above. In the test, I’m going to do some basic operations, like creating an entity, saving an entity, and fetching an entity from the database. While I’ve written a minimal amount of code in this example, the data is really getting saved into a database. You don’t see any SQL happening, but it is getting generated by Hibernate for us. We’re using an in memory H2 database, which goes away once the test is done. But we could easily change the test to save to a database on disk and prove we’ve persisted the test data. Once you grasp how little code you are writing, and how much is happening under the covers for you, you can appreciate what a powerful tool Spring Data JPA is.

ProductRepositoryTest.java

Loading Data Using Spring Data on Startup

Hibernate has a feature to load data on startup. Simply place a file called import.sql on your classpath, and Hibernate will execute the SQL statements in file.

Cool, right?

No, not really. It has us writing SQL statements. What if you’re just doing a prototype? If you change your Entity class, you need to update the SQL. When you’re using Spring Data JPA, this not a very elegant solution. I’m going to shamelessly steal from the Grails community, which has a bootstrap.groovy file which allows us to do things on startup. We have a mature ORM in Hibernate and a really cool tool called Spring Data JPA – why wouldn’t we want to use these tools to load data on startup?

Creating a Product Loader

I previously wrote a post on running code in Spring Boot on Startup. We can use this technique here to utilize the Spring Data JPA repository to populate some data for us to use on startup.

ProductLoader.java

This class implements the ApplicationListner interface, so it gets called upon the ContextRefresedEvent on startup. We’re using Spring to inject the Spring Data JPA repository into the class for our use. In this example, I’m creating two entities and saving them to the database.

ProductLoader.java

Running Product Loader

We still have our Spring Boot application class which was created by the Spring Initializr for us.

SpringBootWebApplication.java

When we run this class, it will startup tomcat for us. In the console log, we can see the output of the log statements from our ProductLoader  class.

To run the Spring Boot application from IntelliJ, simply right click on the SpringBootWebApplication class and select “Run ‘SpringBootWebApplica…'”

run spring boot application from intellij

H2 Database Console

While we still have Tomcat up, We can use the H2 Database Console to browse the H2 database console at the URL http://localhost:8080/console.

Note: If you have not, you will need to setup the H2 database console as explained here.

From the H2 database console, you can see the PRODUCT table has been created by Hibernate, and two records have been inserted via the Spring Data JPA repository we created in this tutorial.

h2 database console showing data saved by Spring Data JPA

Conclusion

In this part of my tutorial series on creating a web application using Spring Boot, I’ve shown you how to setup the H2 database and Spring Data JPA for use. You can see how easy it is to persist data to the database using Spring Data JPA repositories.

In the next part of this tutorial series, I’ll show you how to use data retrieved from the Spring Data JPA repository and display it on a web page using Spring MVC, and how to create and update records.
&nbsp:

Free Introduction to Spring Tutorial

Are you new to the Spring Framework? Checkout my FREE Introduction to Spring Course!.

Get The Code

I’ve committed the source code for this post to github. It is a Maven project which you can download and build. If you wish to learn more about the Spring Framework, I have a free introduction to Spring tutorial. You can sign up for this tutorial in the section below.

The source code for this post is available on github. You can download it here.

Save

1
Share
, ,

Unit testing is the first level of testing software where you write test code that executes a specific functionality in the code to be tested. In most cases, you as a programmer are responsible to deliver unit tested code. The objective is to check if the unit of the software, for example a public method of a class under test, behaves as expected and/or returns the expected data. Unit tests are not done on the production system but as isolated units. If the unit under test have external dependencies, such as an external data source or a Web service, the dependencies are replaced with a test implementation or a mock object created using a test framework. Unit testing is not the only type and it alone cannot handle all testing aspects. Other types of testing, such as integration and functional testing have their own roles in testing software.

In this series of posts we will focus on unit testing with JUnit – one of the most popular framework to test Java code. In this post, we will start by creating and executing a basic unit test, and then in further posts move to specific unit testing aspects.

The core JUnit framework comes in a single JAR file, which you can download, point the classpath to it, and then create and run tests. But in this post, we will learn how to perform unit testing in the real programmer’s way. We will start with Maven, and then move to IntelliJ.

Unit Testing with Maven

You’ve likely heard Maven being referred as a build tool. But, in addition to its capability to build deployable artifacts from source code, Maven provides a number of features for managing the software development life cycle. Unit testing is one such feature, which is incorporated as a test phase in the Maven build lifecycle.

Without going into Maven in depth, let’s start our first JUnit test with Maven.

    1. Download and install Maven if you haven’t done yet.
    2. Open up a command prompt (Windows) or a terminal (*uix or Mac), browse to a working directory to setup the project, and execute the following command.

The preceding archetype:generate command uses the maven-archetype-quickstart template to create a basic Maven project containing a pom.xml file, a App.java class, and a AppTest.java test class in the following directory structure.

In the directory structure above, the pom.xml file, also known as the Maven configuration file is the heart of a Maven project. It is where you define your project configurations – specifically the dependencies of your project. For example, as our project depends on JUnit, we need to declare it as a dependency in the pom.xml file. Although a JUnit dependency will already be present by default, we will update it to point to the latest JUnit version. This is how our final pom.xml file will look like.

pom.xml

Now that we have set up a basic Java class, a test class, and the pom.xml configuration, we can run a unit test.

    1. Execute the mvn test command from the working directory.

This command will run the default AppTest class that Maven generated for us with the following output.

We have executed a JUnit test using Maven. This test passed, but hardly provides any value yet. We will next move to using the IntelliJ IDE to write and execute a more comprehensive test.

Unit Testing in IntelliJ

Using IntelliJ, you can easily create, run, and debug unit tests. Among several other unit testing frameworks, IntelliJ provides built-in support for JUnit. In IntelliJ, you can create a JUnit test class with a click and navigate quickly between test classes and their corresponding target classes to debug test errors. A very useful unit testing feature in IntelliJ is code coverage. With this feature, you can view the exact percentage of methods and even lines of code covered by unit tests in your project.

Let’s import our existing Maven project to IntelliJ and do some unit testing.

Import Maven Project to IntelliJ

If you don’t have IntelliJ installed, download and install the free Community Edition or the 30-day trial of Ultimate Edition from the official website. Once you are done, perform the following steps:

    1. Open IntelliJ.
    2. On the Welcome to IntelliJ IDEA window, click Import Project.

Click Import project

    1. In the Select File or Directory to Import dialog box, browse to the working directory of the Maven project and select the pom.xml file.

Select pom.xml

    1. Click the OK button.
    2. In the Import Project from Maven dialog box that appears, select the Import Maven projects automatically checkbox to synchronize changes between the Maven and InteliiJ projects each time the pom.xml file changes.

Select the Import Maven projects automatically checkbox

    1. Click the Next button through a few more dialog boxes, accepting the default settings, and finally click Finish. The Project window of IntelliJ displays the project structure.

Thct Structure in the IntelliJ Project Windowe Proje

  1. Double click App in the Project window to open it in the code editor.
  2. Replace the default code of the App class with this code.

App.java

In the code above we wrote a concatAndConvertString() method in the App class that accepts two String parameters. The method first concatenates the strings and converts the result to uppercase before returning it.

We will next add a test class to test the concatAndConvertString() method.

Add a Test Class

Let’s go through the steps to add a test class in IntelliJ from scratch.

    1. Delete the default AppTest class from the Project window.
    2. In the Project window create a directory with the name test under main, We will use the test directory to keep the test code separated from the application code.
    3. Right-click test and select Mark Directory As→Test Sources Root.

select Mark Directory As, and then Test Sources Root.

    1. In the code editor where the App class is open, press Shift+F10 and select Create New Test.

Select Create New Test

    1. In the Create Test dialog box that appears, select the jUnit4 radio button and the check box corresponding to the concatAndConvertString() method that we will test.

Select jUnit4 radio button and the method that we will test

  1. Click the OK button. JUnit creates the AppTest class with a testConcatAndConvertString() method decorated with the @Test annotation. This annotation tells JUnit to run the method as a test case. In the test method, we will write the code to test the concatAndConvertString() method of App.

AppTest.java

In Line 12 of the example above, we called the assertEquals() method, which is one of the several JUnit assertion methods. This overloaded method checks whether two String objects are equal. If they are not, the method throws an AssertionError. In our example, we called the assertEquals() method by passing the expected string value (HELLOWORLD) as the first parameter and the actual value that the concatAndConvertString() method returns as the second parameter.

Run the Unit Test

To run the test, select Run AppTest from the Run menu of IntelliJ or press Shift+F10. The Run window displays the test result. A green highlight box indicates that the test completed without any failure.

Green highlight box indicating a passed test

To know how test failures are reported, change the value of the expectedValue variable to HelloWorld and press Shift+F10. The Run dialog box displays a red progress bar to indicate the test failure along with a comparison failure message.

Red Progress Bar Indicating a Failed Test

Revert the the expectedValue variable to its original value before you close IntelliJ.

Summary

At this point, if you are thinking Why not just use System.out.println() for unit testing? Then you are thinking wrong. Inserting System.out.println() for debugging into code is undesirable because it requires manually scanning the output, every time the program is run, to ensure that the code is doing what’s expected. Imagine doing this in an enterprise application having hundreds and thousands of lines of code. On the other hand, unit tests examine the code’s behavior on runtime from the client’s point of view. This provides better insight on what might happen when the software is released.

Whenever you are writing code, you should be writing unit tests too. Writing unit tests will catch programming errors and improve the quality of your code. Many professional developers advocate doing Test Driven Development (TDD), where you write your unit tests before you write the application code.

Either way if you write your unit tests before or after you write the application code, the unit tests become a valuable asset for instrumenting your code. As the code base grows, you can refactor things as needed, and have more confidence that your changes will not have unintended consequences (ie where you change one thing, and accidently break something else).

In part 2 of my tutorial series on unit testing with JUnit I’ll take a deeper look at JUnit Assertions, JUnit Annotations, and JUnit Test Suites.

Unit Testing with the Spring Framework

Testing is an integral part of Enterprise Application Development process with the Spring Framework. The architecture of the Spring Framework lends itself to modular code and easier unit testing.  Spring provides testing support through the TestContext Framework that abstracts the underlying testing framework, such as JUnit and TestNG. You can use it by setting SpringJUnit4ClassRunner.class as the value for the @RunWith annotation. This tells Spring to use the test runner of TestContext instead of JUnit’s built in test runner. I’ve written a more in depth post about testing Spring applications with JUnit here.

1
Share
,

You will find a greater need for Integration tests as your testing requirements become more complex when you’re supporting enterprise application development using the Spring Framework. Sometimes, allowing Spring to manage the beans makes your testing easier, sometimes you want to test parts of your Spring Configuration, sometimes you’ll need to wire in a Mock component for your tests.

Spring and Junit are a powerful combination. You can easily bring in a custom Spring configuration to meet the needs of your test scenario.

Spring Configuration

There are number of different ways to create Spring Beans. In this example I’m going to use a Java configuration. Below is my Spring Configuration class for our integration test.

ProductServiceTestConfig

Note the use of the annotation @Configuration  at the top of the class. This designates the class as a Spring Configuration class. The annotation @Bean  tells Spring to use this method to load a Spring bean into the context. The default behavior of Spring is to use the name of the method as the bean name. This behavior is easily overridden by passing a name to the bean annotation as @Bean(name = "customBeanName"). In this configuration class, I’m defining two spring beans. The same test stub bean we used in the previous unit test example and the product service implementation. Notice that I do not manage the injection of the repository bean into the service bean. I allow the Spring Framework to manage the dependency injection.

Spring and JUnit Configuration

To support Spring and JUnit, we need to add two new annotations to our test class. The first annotation is @RunWith(SpringJUnit4ClassRunner.class) . The annotation is provided by the JUnit team, which is a API to allow for the extension of JUnit to allow for a customized test runner class. Within this annotation, we’re passing in the class SpringJUnit4ClassRunner.class , this is the test runner class supplied by the Spring Framework. This custom test runner is what enables the Spring Context. Your test class in effect becomes a Spring Bean, and is managed in the Spring context. The second annotation we need to use is @ContextConfiguration, this allows for us to specify the configuration for the Spring Context. The configuration of this annotation is very versatile. As the complexity of your application grows, so will your configuration. For our example today, our needs are not very complex. I only have one configuration class to bring into the Spring Context. I can do this simply by passing the class name to the annotation using the classes property like: @ContextConfiguration(classes = {ProductServiceTestConfig.class}). Through the use of these two annotations, when I run the JUnit test, the Spring Context will be started and the beans we’ve specified in the configuration will be available for use in our test.

JUnit Test

By convention, I’m naming my Integration Test with the suffix of ‘IT’. Traditionally, you will name your unit tests with the suffix of ‘Test’ or ‘Tests’, and your integration tests with the suffix of ‘IT’. This does not affect how JUnit runs the tests. But it does have ramifications later when building with tools such as Maven and deploying and reporting from Continuous Build servers such as Jenkins.

ProductServiceImplIt

The class below is the same test we looked at above as a Unit test, but now it’s an Integration test, and we are using Spring to manage the dependency injection. Here we have the test class annotated with the annotations we just discussed above. Since the class is now managed by Spring, we can use the @Autowired annotation to inject our service bean into the test. This bean is a Spring Bean, which is configured and managed by Spring. Thus it will have the repository injected for us as we specified in our test configuration class.

Free Introduction to Spring Tutorial

Are you new to the Spring Framework? Checkout my Free Introduction to Spring Online Tutorial.
0
Share
, ,

Testing software has many meanings, which are often confused. In the last decade or so, we’ve seen agile development methodologies go mainstream in the modern enterprise. These methodologies are often misunderstood and misused. Some times they assume you have clean testable code. Often, when dealing with legacy applications, you simply don’t.

I’ve encountered legacy Java code which had methods over 2,000 lines long. One method, 2,000 lines of code. A clear violation of the Single Responsibility Principle and other Principles of Object Oriented Design. How do you unit test this method? Answer is, you can’t. It’s pretty much impossible to ensure proper unit test coverage of a method with 2,000 lines of code.

You can read a lot about agile software development and testing software, but one often overlooked fact is you’re code must first be testable. If you don’t have clean testable code, you will be limited in the benefits you can receive from automated testing.

The various types of testing are often misused in discussion. I once overheard an executive say println statements were unit tests. I’m sorry, they are not. println statements are NOT UNIT TESTS.

I’d like to offer my definition of categories for testing software.

Unit Tests

The phase ‘Unit Test’ is often misused. People often refer to tests as “Unit Tests” when they are actually a different type of test. Characteristics of Unit Tests:

  • Unit tests are small, short, lightweight tests.
  • Should roughly focus on one public method call of the class under test.
  • Should be ‘unit-y’.
  • Should not interact with the database, any external services, or bring up a Spring Context.

Remember keep your unit tests light and fast. JUnit is the most popular tool for doing unit tests in Java. TestNG is also very popular.

Integration Tests

Integration Tests are a broader category of automated software tests. Often if your test fails the characteristics of a ‘Unit’ test, its actually a integration test. Characteristics of Integration Tests:

  • Tests the interaction of one or more classes.
  • Might interact with a database.
  • Uses a Spring Context.
  • Talks to a web service or message queue.
  • Runs in a container, such as tomcat.
  • Needs a web context.

Because Integration Tests are doing more and interacting with more stuff, they are expected to run longer than unit tests. A true unit test will complete in a fraction of a second, while an integration test can take several seconds to complete.

JUnit is also a popular tool for writing integration tests. Keep in mind, just because you’re using ‘JUnit’, it does not mean your test is a ‘Unit Test’. Once you interact with a database or bring up a Spring Application Context, your test is an Integration Test.

Functional Tests

Functional tests are as they sound. ‘Functional’. When running functional tests, it’s common for your code to be deployed in its run time configuration and you’re simulating the actions of the functional client. Characteristics of Functional Tests:

  • Your code is running as is deployed. Possibly in an embedded Tomcat instance or deployed to a development server.
  • Your test client is acting as a functional client. You might be using Selenium to drive a web browser to test the web pages being rendered by your software, or maybe acting as a web service client to test a web service you developed.

Functional tests are by far the slowest, yet most complex tests. They build upon your integration tests, and automate the testing of your software as a client would interact with it.

Conclusion

I’ve presented some basic rules of thumb when it comes to how to describe your tests. In the real world, you can easily get into shades of gray. And it’s easy to misuse these terms. I’m guilty of it. I often mistakenly refer to integration tests as unit tests.

When you’re testing your software, keep in mind each type of test has its role. It would be a mistake to think you need all unit tests and no functional tests. Or to think that your application is some how special and you can get proper code coverage from just writing functional tests.

In reality, you need a combination of all three. The majority of your tests should be unit tests, then integration tests, then the fewest (yet still important), functional tests.

4
Share