Top 10 Testing Frameworks and Libraries for Java Developers

Top 10 Testing Frameworks and Libraries for Java Developers

Want to up your automation testing game? Here are overviews of 10 great testing frameworks and libraries and preferred use cases.

Want to up your automation testing game? Here are overviews of 10 great testing frameworks and libraries and preferred use cases.

           

Recently, I have written some articles about what Java developers should learn this year, e.g. programming languages, libraries, and frameworks, but if you have just one thing to improve or learn, then that must be your automation testing skills.

Testing is one of the disciplines that separates professional developers from amateur ones. It's not about following TDD, BDD, or whatever testing methodologies, but at the very minimum level, you must write code to test your code automatically.

Many Java developers write unit tests and integration tests that automatically run during build time, mostly by using continuous integration tools like Jenkins or TeamCity.

If some of you are wondering why a programmer should focus on automation testing, then let me tell you that the importance of automation testing is growing exponentially due to more awareness and emergence of DevOps.

Companies generally prefer programmers who are good at writing unit tests and show good knowledge of various unit testing frameworks, libraries, and tools e.g. JUnit, Selenium, REST-Assured, Spock framework, etc.

As a Java developer, we work on very different areas, starts from writing core Java code to creating JSP pages, writing REST APIs, and sometimes even creating Groovy scripts for build automation. That's why we also need to be aware of different tools we can use to automate testing.

For example, I only knew JUnit for a long time, but when I had to test my JSP pages, I was clueless until I found Selenium. Same goes with REST Assured because I usually test my REST API using curl commands, but REST Assured takes the unit testing of REST APIs to another level.

10 Useful Unit and Integration Testing tools for Java Programmers

Since I believe a programmer is as good as their tools, I always try to learn and explore new tools and libraries in my free time, and this list is part of that research.

In this article, I am going to share 10 of the best and essential tools, frameworks, and libraries that can help Java developers writing unit tests and integration tests on their various Java projects.

1. JUnit

I don't think JUnit needs any introduction. Even if you are a beginner Java programmer, you might have heard about it. It allows you to write unit tests for your Java code.

Almost all major IDEs, e.g. Eclipse, NetBeans, and IntelliJ, provide JUnit integrations, which means you can both write and run the unit test right from those IDEs.

Most of us are still using JUnit 4, but JUnit 5 is already released and probably the next thing to look at this year. You can use JUnit for both unit and integration testing and it also supports Java 8 features.

Btw, if you are a completely new in the unit testing world, particularly in Java unit testing then this JUnit and Mockito crash course is a good starting point.

2. REST Assured

Testing and validating REST services in Java is harder than in dynamic languages such as Groovy.

REST Assured brings the simplicity of using these languages into the Java domain. It's a great tool for REST API integration tests.

If you want to learn more, you can also check REST API Testing Automation: via REST Assured & HTTP Client course. 

3. Selenium

Selenium is probably the most popular tool for Java UI testing, which allows you to test your JSP pages without launching them in a browser.

You can test your web application UI using JUnit and Selenium. It even allows you to write web application acceptance tests.

If you want to learn Selenium,  Selenium WebDriver with Java - Basics to the Advanced course is best place to start with. 

4. TestNG

TestNG is a testing framework inspired by JUnit and NUnit but introducing many new functionalities that make it more powerful and easier to use, such as annotations, running your tests in arbitrarily big thread pools with various policies available (all methods in their own thread, one thread per test class, etc).

The gap between JUnit and TestNG has reduced because of using annotations from JUnit 4 and integrating the Hamcrest matchers as well but it's up to you.

If you decide to learn TestNG for unit testing your Java code then TestNG Complete Bootcamp For Beginners - Novice To Ninja is a good course to start with.

5. Mockito

There are many mocking frameworks for Java classes, e.g. PowerMock and JMock, but I personally like Mockito for their simple API, great documentation, and lots of examples.

Mocking is one of the essential techniques of modern-day unit testing, as it allows you to test your code in isolation without any dependency, and that's why I encourage every Java developer to learn a mocking framework along with JUnit.

My favorite mocking framework is Mockito, but if you like, you can also explore PowerMock or JMock.

If you also like Mockito and decide to learn this framework then Mockito Tutorial: Learn mocking with 25 Junit Examples is a good course to start with.

6. Spock Framework

Spock is another testing and specification framework for Java and Groovy applications. It's written in Groovy, which makes it a very expressive and to-the-point specification language.

When you use Spock, your test will become more readable and easier to maintain and thanks to its JUnit runner, Spock is compatible with most IDEs, build tools, and continuous integration servers.

Unfortunately, I didn't find a useful course to learn Spock framework but Java Testing with Spock book is a good resource to start with.

7. Cucumber

Cucumber is another great tool for automated integration tests, but what makes it different from other tools in the same category is its specification capability.

Cucumber merges specification and test documentation into one cohesive whole living documentation and since they will be automatically tested by Cucumber, your specifications are always banged up-to-date.

If you want to build a start to finish web automation testing framework and simulate user behavior on a web application then Selenium WebDriver with Java & Cucumber BDD is a good course to both learn and implement Cucumber in your project. 

8. Spring Test

Spring MVC comes with a very useful test framework that allows doing in-depth testing without even involving a web container.

It is one of the most useful libraries for writing automated tests to Spring applications. It provides a first-class support for writing unit and integration tests to Spring-powered applications, including MVC controllers.

There is also a Spring Test DbUnit that integrates the Spring Test framework with DbUnit and a Spring Test MVC HtmlUnit, which integrates the Spring Test MVC framework with HtmlUnit.

By using these tools you can easily test your Spring MVC application in an automated way.

9. DBUnit

A database is an integral part of many Java applications, both core Java and web applications, and probably the biggest obstacle while doing unit testing.

It's not reliable to connect to Dev or UAT databases for integration tests because anyone can change the data and schema, e.g. tables and stored procedures, and that will cause your automated integration tests to fail.

DbUnit is a JUnit extension that can be used to initialize the database into a known state before each integration test to ensure that the database contains the correct data.

DbUnit has its own issues, but it is a very useful tool because it helps us to separate the test data creation from the tested code.

10. Robot Framework

The Robot Framework is a Python-based generic test automation framework for acceptance testing and acceptance test-driven development.

It is a keyword-driven testing framework that uses tabular test data syntax. You can use it to test distributed, heterogeneous applications, where verification requires touching several technologies and interfaces.

If you decide to learn this wonderful framework for integration test, then Udemy's Robot Framework Test Automation is a great resource to start with.

It's a two-part course which covers the basic and advanced features of Robot framework.

Conclusion

That's all about some of the essential unit testing and integration testing tools, frameworks, and libraries for Java developers.

There are many more libraries that I have not included in this list, e.g. AssertJ and Hamcrest, which can help you to write beautiful and fluent tests — but take things slowly.

To start with, learn a tool or library that you can use in your day-to-day work. For example, if you are working with Java UIs, then you should first learn Selenium because then you can focus on this tool more.

Similarly, if you are working on REST APIs then learn REST Assured (See REST with Spring). If you are doing a lot of core Java work, then JUnit 5 is probably the first library you should look at.

Test a REST API with Java

Test a REST API with Java

This tutorial focuses on the basic principles and mechanics of testing a REST API with live Integration Tests (with a JSON payload).

This tutorial focuses on the basic principles and mechanics of testing a REST API with live Integration Tests (with a JSON payload).

1. Overview

The main goal is to provide an introduction to testing the basic correctness of the API – and we’re going to be using the latest version of the GitHub REST API for the examples.

For an internal application, this kind of testing will usually run as a late step in a Continuous Integration process, consuming the REST API after it has already been deployed.

When testing a REST resource, there are usually a few orthogonal responsibilities the tests should focus on:

  • the HTTP response code
  • other HTTP headers in the response
  • the payload (JSON, XML)

Each test should only focus on a single responsibility and include a single assertion. Focusing on a clear separation always has benefits, but when doing this kind of black box testing is even more important, as the general tendency is to write complex test scenarios in the very beginning.

Another important aspect of the integration tests is adherence to the Single Level of Abstraction Principle – the logic within a test should be written at a high level. Details such as creating the request, sending the HTTP request to the server, dealing with IO, etc should not be done inline but via utility methods.

2. Testing the Status Code
@Test
public void givenUserDoesNotExists_whenUserInfoIsRetrieved_then404IsReceived()
  throws ClientProtocolException, IOException {
  
    // Given
    String name = RandomStringUtils.randomAlphabetic( 8 );
    HttpUriRequest request = new HttpGet( "https://api.github.com/users/" + name );
 
    // When
    HttpResponse httpResponse = HttpClientBuilder.create().build().execute( request );
 
    // Then
    assertThat(
      httpResponse.getStatusLine().getStatusCode(),
      equalTo(HttpStatus.SC_NOT_FOUND));
}

This is a rather simple test – it verifies that a basic happy path is working, without adding too much complexity to the test suite.

If for whatever reason, it fails, then there is no need to look at any other test for this URL until this is fixed.

3. Testing the Media Type
@Test
public void
givenRequestWithNoAcceptHeader_whenRequestIsExecuted_thenDefaultResponseContentTypeIsJson()
  throws ClientProtocolException, IOException {
  
   // Given
   String jsonMimeType = "application/json";
   HttpUriRequest request = new HttpGet( "https://api.github.com/users/eugenp" );
 
   // When
   HttpResponse response = HttpClientBuilder.create().build().execute( request );
 
   // Then
   String mimeType = ContentType.getOrDefault(response.getEntity()).getMimeType();
   assertEquals( jsonMimeType, mimeType );
}

This ensures that the Response actually contains JSON data.

As you might have noticed, we’re following a logical progression of tests – first the Response Status Code (to ensure that the request was OK), then the Media Type of the Response, and only in the next test will we look at the actual JSON payload.

4. Testing the JSON Payload
@Test
public void
  givenUserExists_whenUserInformationIsRetrieved_thenRetrievedResourceIsCorrect()
  throws ClientProtocolException, IOException {
  
    // Given
    HttpUriRequest request = new HttpGet( "https://api.github.com/users/eugenp" );
 
    // When
    HttpResponse response = HttpClientBuilder.create().build().execute( request );
 
    // Then
    GitHubUser resource = RetrieveUtil.retrieveResourceFromResponse(
      response, GitHubUser.class);
    assertThat( "eugenp", Matchers.is( resource.getLogin() ) );
}

In this case, I know the default representation of GitHub resources is JSON, but usually, the Content-Type header of the response should be tested alongside the Accept header of the request – the client asks for a particular type of representation via Accept, which the server should honor.

5. Utilities for Testing

We’re going to use Jackson 2 to unmarshall the raw JSON String into a type-safe Java Entity:

public class GitHubUser {
 
    private String login;
 
    // standard getters and setters
}

We’re only using a simple utility to keep the tests clean, readable and at a high level of abstraction:

public static <T> T retrieveResourceFromResponse(HttpResponse response, Class<T> clazz)
  throws IOException {
  
    String jsonFromResponse = EntityUtils.toString(response.getEntity());
    ObjectMapper mapper = new ObjectMapper()
      .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    return mapper.readValue(jsonFromResponse, clazz);
}

Notice that Jackson is ignoring unknown properties that the GitHub API is sending our way – that’s simply because the Representation of a User Resource on GitHub gets pretty complex – and we don’t need any of that information here.

6. Dependencies

The utilities and tests make use of the following libraries, all available in Maven central:

7. Conclusion

This is only one part of what the complete integration testing suite should be. The tests focus on ensuring basic correctness for the REST API, without going into more complex scenarios,

For example, the following are not covered: Discoverability of the API, consumption of different representations for the same Resource, etc.

The implementation of all these examples and code snippets can be found over on Github – this is a Maven-based project, so it should be easy to import and run as it is.

Top 5 Java Test Frameworks for Automation in 2019

Top 5 Java Test Frameworks for Automation in 2019

In this article, you'll learn about the top 5 Java test frameworks for automation testing in 2019

Check out this post to learn more about the top Java test frameworks for automation testing.

For decades, Java has been the most preferred programming language for developing the server side layer of an application. Although JUnit has been there with the developers for helping them in automated unit testing, with time and the evolution of testing, when automation testing is currently on the rise, many open-source frameworks have been developed that are based on Java and varying a lot from JUnit in terms of validation and business logic. Here, I will be talking about the top five Java test frameworks of 2019 for performing test automation with Selenium WebDriver and Java. I will also highlight what is unique about these top Java test frameworks.

JUnit

Kent Beck and Erich Gamma developer JUnit, which is an instance of xUnit. The main purpose behind it was to enable Java developers for scripting and executing repeatable test cases. It is usually used to test small chunks of code. You can also perform automation testing of a website by integrating JUnit with Selenium WebDriver for Java test automation. Whenever any new piece of code is added, you will be required to re-execute the entire test cases and make sure that there is no breakage.

What Are the Prerequisites?

The framework is highly compatible with Selenium WebDriver for Java, with the reason being that JUnit is a framework based on Java. As some prerequisites, you will need to:

  • Have the latest version of JDK installed in your workstation.
  • Download the latest version of JUnit and set up the environment.
  • Have a good knowledge of application development in an object-oriented programming language, especially Java.

Advantages and Disadvantages of Using JUnit?

There are several advantages to JUnit.

  • Have the latest version of JDK installed in your workstation.
  • Download the latest version of JUnit and set up the environment.
  • Have a good knowledge of application development in an object-oriented programming language, especially Java.

The only disadvantage of JUnit is:

  • Have the latest version of JDK installed in your workstation.
  • Download the latest version of JUnit and set up the environment.
  • Have a good knowledge of application development in an object-oriented programming language, especially Java.

Is JUnit the Top Java Test Framework for You?

Both JUnit, as well as TestNG, perform the same job. And their features are almost the same, except dependency tests are not performed using JUnit and the implementation procedure of parameterized test is different in both the frameworks. Also, since JUnit is being used for a long time, there is better community support and it has been defined as the standard for unit testing using Selenium WebDriver for Java-based applications. Although TestNG has few users, the community is pretty huge and growing every day. So, we can conclude that the selection between TestNG or JUnit for a Java test framework depends entirely upon the application’s nature and requirement.

If you wish to get started with JUnit as your Java test framework, here is a step-by-step process of performing automated testing with JUnit and Selenium for browser compatibility.

JBehave

We all know about Behavior Driven Development or BDD. It is the type of testing that describes acceptance testing in a transparent manner to the business users. JBehave is another Java test framework used for BDD testing, mostly used with Selenium WebDriver for Java. The primary objective behind the introduction of JBehave is to make it possible for newcomers to easily understand and get familiar with BDD. It is kind of a design philosophy that makes the testing phase of an application more based on its behavior.

What Are the Prerequisites?

The ideal way to use JBehave is by integrating with Eclipse. For that, apart from JDK1.7 and above and any Eclipse IDE above Indigo, you will need several jar files like:

  • Have the latest version of JDK installed in your workstation.
  • Download the latest version of JUnit and set up the environment.
  • Have a good knowledge of application development in an object-oriented programming language, especially Java.

Advantages and Disadvantages of JBehave

Like all other BDD testing frameworks, JBehave is also advantageous in many ways.

  • Have the latest version of JDK installed in your workstation.
  • Download the latest version of JUnit and set up the environment.
  • Have a good knowledge of application development in an object-oriented programming language, especially Java.

Well, there is only one disadvantage of JBehave just like any other BDD testing tool.

  • Have the latest version of JDK installed in your workstation.
  • Download the latest version of JUnit and set up the environment.
  • Have a good knowledge of application development in an object-oriented programming language, especially Java.

Is JBehave The Top Java Test Framework For You?

JBehave works the same way as Serenity. However, if you are aiming to make your automated acceptance tests more efficient, it is ideal to integrate Serenity along with JBehave for utilizing a better testing experience. This is because Serenity’s core concept is based on BDD development and it also enables the users to write a powerful and rich test report. We’ll discuss more on it in the following section.

Serenity

Serenity is an open-source library meant for behavior-driven testing. The framework helps you to write acceptance criteria, which are well-structured and more maintained. It extends the functionality of JUnit and WebDriver. Initially, it was known as Thucydides. The reason behind its name change was nothing but the difficulty in pronunciation. Still, the old name can be used while referring.

What Are the Prerequisites for Installing Serenity?

Since the framework is Java-based, you will obviously need knowledge and experience in Java or any other object-oriented programming language. Apart from that, in your workstation, you will need:

  • Have the latest version of JDK installed in your workstation.
  • Download the latest version of JUnit and set up the environment.
  • Have a good knowledge of application development in an object-oriented programming language, especially Java.

Advantages and Disadvantages of Serenity

Let’s take a look at the advantages of Serenity brought into the world of behavior driven development.

  • Have the latest version of JDK installed in your workstation.
  • Download the latest version of JUnit and set up the environment.
  • Have a good knowledge of application development in an object-oriented programming language, especially Java.

The only disadvantage of Serenity is just like JBehave. Constant communication between the project participants is required in order to utilize its complete feature of supporting a behavior driven development.

Is Serenity the Best Java Test Framework for You?

The tool is mainly used for reporting acceptance criteria. However, the reports written using Serenity are much informative and rich than JBehave or any other BDD framework. It also helps developers to write automation test case scenarios of better quality and also provides support for RestAssured and Selenium WebDriver, making it faster and simpler for the tester to write automation based acceptance test criteria.

TestNG

Cedric Beust created TestNG, which is an open-source, Java-based automation testing framework inspired by JUnit. However, it is much more powerful. The NG means Next Generation in TestNG. The framework is designed to perform in a better manner during integration. The framework helps developers with features like sequencing, grouping, and parameterizing, thereby making the new test cases more flexible and eliminating the drawbacks of frameworks used earlier.

Prerequisites for Installing TestNG

For installing TestNG, you will need:

  • Have the latest version of JDK installed in your workstation.
  • Download the latest version of JUnit and set up the environment.
  • Have a good knowledge of application development in an object-oriented programming language, especially Java.

Advantages and Disadvantages of TestNG

Apart from overcoming the drawbacks of older frameworks, there are several advantages of TestNG.

  • Have the latest version of JDK installed in your workstation.
  • Download the latest version of JUnit and set up the environment.
  • Have a good knowledge of application development in an object-oriented programming language, especially Java.

The only disadvantage is:

  • Have the latest version of JDK installed in your workstation.
  • Download the latest version of JUnit and set up the environment.
  • Have a good knowledge of application development in an object-oriented programming language, especially Java.

Is TestNG the Best Java Test Framework for You?

Although JUnit performs all the same functionalities as TestNG, it has certainly has its limitations. JUnit is perfect when testing is done in isolation. But when there are dependencies; you will not have any control over which test is executed first. TestNG helps you by allowing you to run the test cases in any order you want. Besides, it also helps in parameterized testing. Although this feature is already present in JUnit 4.5, TestNG is much more effective. If your project is complicated and you may need more than a hundred test cases, it is ideal to take some time and set up TestNG instead of depending on JUnit.

If you are new to TestNG, then here is a complete guide for running your first TestNG automation script for performing automated cross-browser testing using Selenium WebDriver with Java.

Selenide

Powered by Selenium, Selenide is a popular tool for writing stable, precise, and expressive UI test cases for a Java application. Testing of modern web technologies like Ajax has certain complications like a timeout. WebDriver is the popular tool for UI tests, yet it lacked the feature to deal with a timeout. Selenide deals with all these problems in a simple manner. Also, it’s easier to grab and learn. You don’t need any requirement for Google and search for tutorials. All you need to do is focus on the business logic, and in just a few simple lines of codes, your job will be done.

What Are the Prerequisites for Using Selenide?

Installation of Selenide is as simple as it can be. If you are using Maven, you will need to add the following lines in your pom.xml file.

<dependency>     
<groupId>com.codeborne</groupId>     
<artifactId>selenide</artifactId>     
<version>5.1.0</version>     
<scope>test</scope> 
</dependency>

If you are using Ivy in the ivy.xml file, you will need to add:

<ivy-module>   
<dependencies>     
<dependency org="com.codeborne" name="selenide" rev="5.1.0"/>   
</dependencies> 
</ivy-module>

And just like that, the framework is ready for you to start testing.

Advantages and Disadvantages of Selenide?

In the front-end layer of an application, where Java is used on the server side, the most common problem faced by a tester is timeouts. The test cases which you wrote may work fine at present, but after a few days, maybe some Ajax request will take up some more time than it does now or some JavaScript will run slower. Also, your system may run another process at the same time, resulting in the failure of your test case. What’s more unfortunate, you may spend days finding out the source of those problems. Selenide helps you by:

  • Have the latest version of JDK installed in your workstation.
  • Download the latest version of JUnit and set up the environment.
  • Have a good knowledge of application development in an object-oriented programming language, especially Java.

Until now, we have not found any notable disadvantage of using Selenide. Let us know if you have found any limitations that may impact your work.

Is Selenide the Best Java Test Framework for You?

For UI testing, there is no better Java-based framework apart from Selenium WebDriver, the parent framework of Selenide. Obviously, WebDriver cannot solve problems caused by Ajax Timeout or slow running JavaScript or any Dynamic Content that takes time to load. To overcome problems, we previously used “ wait_until” or “ sleep” methods in our test cases. With Selenide, we don’t need to think about those problems anymore. Just focus on the business logic and the test cases will work fine in serving their purpose.

If you plan to opt Selenide as your Java test framework for automation testing, then here is a guide to help you run Selenium automation tests using Selenide, IntelliJ, and Maven.

In the current Agile age, developers are also required to get involved in testing. Knowledge and knowing the importance of testing is what separates professional Java developers from amateurs. It is not necessary that you should be an expert, but at least you should have the basic knowledge to write test cases that can automatically validate your code. In this article, we have gone through five tools which are preferred by developers worldwide for UI testing, unit testing, and BDD testing of an application. Based on the comparison, we can conclude that if you are sincere in your job and want to become an expert developer as well as a tester, the tools mentioned above are something on which you will find useful in your daily assignments.

Best Java Unit Testing Frameworks You Must Know In 2019

Best Java Unit Testing Frameworks You Must Know In 2019

Unit testing is an important skill for programmers. With that said, what are the best frameworks you can use to write great unit tests in Java?

Originally published by Ranga Karanam at https://dzone.com
What We Will Learn
  • What are the best Java unit testing frameworks?
  • What is JUnit? How do you use JUnit for unit testing?
  • What is Mockito?
  • What is mocking?
  • How do you write unit tests with Junit, Mockito, AssertJ, and other frameworks?
  • What is the best Java unit testing framework for writing great asserts?
The Base Unit Testing Framework — JUnit/TestNG

Whenever you write a unit test, you execute the code and then check its output. You need a basic framework in place to run a large number of tests in a similar manner.

JUnit

The JUnit framework provides a basic framework that allows you to specify the test that you want to run, along with its inputs, and the result that comes out of it.

Have a look at the following test:

@Test
public truncateAInFirst2Positions_AinFirstPosition() {
assertEquals("CD", helper.truncateAInFirstPosition("ACD"));
}

Notice the annotation @Test used the decorate the test. The name of the test is descriptive and demonstrates the intent of the test. JUnit provides different kinds of assertion methods to check the result of the code executed within a test. These include assertEquals(), assertTrue(), and assertFalse().

Now have a look at this one that tests a negative scenario:

@Test
public testAreFirstAndLastTwoCharactersTheSame_BasicNegativeScenario() {
assertFalse(helper.areFirstAndLastTwoCharactersTheSame("ABCD"));
}

JUnit also supports something called parameterized tests.

TestNG

TestNG is a good alternative to JUnit to write unit tests and makes it easy to write customized tests. Suppose you have the test data needed to execute your suites in a spreadsheet or an XML document. TestNG makes it easy to get the data for tests to be written around them.

At a high level, JUnit and TestNG are frameworks that enable you to write tests and check results. If a test succeeds, you see a green bar. Or else, a red bar.

Mocking Frameworks — Mockito and EasyMock

When writing unit tests, it is often required to mock or stub dependencies.

Mocking is preferred to stubbing. There are a couple of great options for mocking in the Java world — Mockito and EasyMock.

Mockito

Have a look at the following example:

public class SomeBusinessImpl {
private DataService dataService;
//Constructor - public SomeBusinessImpl(DataService dataService) { //... }
int findTheGreatestFromAllData() {
int[] data = dataService.retrieveAllData();
int greatest = Integer.MIN_VALUE;
for (int value : data) {
if(value > greatest)
greatest = value;
}
return greatest;
}
}

The value returned by the findTheGreatestFromAllData() depends on the data that comes back from the data service.

To be able to write a good unit test for this method, you need to mock this dependency out.

Have a look at the following test for the class:

@Test
public void testFindTheGreatestFromAllData() {
DataService dataServiceMock = mock(DataService.class);
when(dataServiceMock.retrieveAllData())
.thenReturn(new int[] {24, 15, 3});
SomeBusinessImpl businessImpl = new SomeBusinessImpl(dataServiceMock);
int result = businessImpl.returnTheGreatestFromAllData();
assertEquals(24, result);
}

Mockito makes it easy to mock the DataService. Here, we use its mock() method to mock the DataService and inject the mock into the SomeBusinessImpl class.

Mockito also provides great annotations to inject mocks automatically.

@RunWith(MockitoJUNitRunner.class)
public class SomeBusinessMockAnnotationsTest {
@Mock
DataService dataServiceMock;
@InjectMocks
SomeBusinessImpl businessImpl;
@Test
public void testFindTheGreatesFromAllData() {
when(dataServiceMock.retrieveAllData())
.thenReturn(new int[] {24, 15, 3});
assertEquals(24, businessImpl.findTheGreatestFromAllData());
}
}

Annotations such as @Mock and @InjectMocks take care of what their names suggest, thereby making the test code smaller and more readable.

EasyMock

EasyMock is also a mocking framework that can be effectively used in unit tests. It is a popular alternative to Mockito.

Mocking Complex Scenarios — Use PowerMock

Frameworks such as Mockito allow you to insert mocks only when the code design is good. When the design is not so good, PowerMock comes to your rescue.

Powermock is useful when you want to mock static methods, constructors, and private methods.

Have a look at the following code:

interface Dependency {
List<Integer> retrieveAllStats();
}
public class SystemUnderTest {
private Dependency dependency;
public int methodUsingAnArrayListConstructor() {
ArrayList list = new ArrayList();
return list.size();
}
public int methodCallingAStaticMethod() {
//private methodUnderTest calls static method SomeClass.staticMethod
List<Integer> stats = dependency.retrieveAllStats();
long sum = 0;
for(int stat : stats) {
sum += stat;
}
return UtilityClass.staticMethod(sum);
}
private long privateMethodUnderTest() {
List<Integer> stats = dependency.retrieveAllStats();
long sum = 0;
for(int stat : stats) {
sum += stat;
}
return sum;
}
}

Here, SomeClass.staticMethod is a static method that is defined. Therefore, we have a need to mock it out. We need to test the method methodCallingAStaticMethod() after this mock. Have a look at the following test code:

@RunWith(PowerMockRunner.class)
@PrepareForTest({UtilityClass.class})
public class PowerMockitoMockingStaticMethodTest {
@Mock
Dependency dependencyMock;
@InjectMocks
SystemUnderTest systemUnderTest;
@Test
public void powerMockito_MockingAStaticMethodCall() {
when(dependencyMock.retrieveAllStats()).thenReturn(Arrays.asList({1, 2, 3}));
PowerMockito.mockStatic(UtilityClass.class);
when(UtilityClass.staticMethod(anyLong())).thenReturn(150);
assertEquals(150, systemUnderTest.methodCallingAStaticMethod);
//Verify the specific method call
//First, call PowerMockito.verifyStatic()
//Second, call the method to be verified
PowerMockito.verifyStatic(); 
UtilityClass.staticMethod(1 + 2 + 3);
//verify exact number of calls
//PowerMockito.verifyStatic(Mockito.times(1));
}
}

Here, we have written code that allows us to mock out a static method.

It is also possible to mock a constructor:

@RunWith(PowerMockRunner.class)
@PrepareForTest({UtilityClass.class})
public class PowerMockitoMockingConstructorTest {
private static final int SOME_DUMMY_SIZE = 100;
@Mock
Dependency dependencyMock;
@InjectMocks
SystemUnderTest systemUnderTest;
@Test
public void powerMockito_MockingAConstructor throws Exception {
ArrayList<String> mockList = mock(ArrayList.class);
stub(mockList.size()).toReturn(SOME_DUMMY_SIZE);
PowerMockito.whenNew(ArrayLst.class).withAnyArguments().thenReturn(mockList);
int size = systemUnderTest.methodUsingAnArrayListConstructor();
assertEquals(SOME_DUMMY_SIZE, size);
}
}

When the constructor is called, the mockList is returned instead.

PowerMock can also be used to mock private methods:

@RunWith(PowerMockRunner.class)
@PrepareForTest({UtilityClass.class})
public class PowerMockitoMockingPrivateMethodTest {
@Mock
Dependency dependencyMock;
@InjectMocks
SystemUnderTest systemUnderTest;
@Test
public void powerMockito_CallingAPrivateMethod throws Exception {
when(dependencyMock.retrieveAllStats()).thenReturn(Arrays.asList({1, 2, 3}));
long value = (Long) WhiteBox.invokeMethod(systemUnderTest,
"PrivateMethodUnderTest");
assertEquals(6, value);
}

Note that you cannot directly invoke a private method from test code. We are using the functionality of a class named WhiteBox, to which we pass the string name of the private method.

Writing Great Asserts Using AssertJ/Hamcrest

Whenever you write tests, you want to have great assertions.

AssertJ

Have a look at the folowing code:

public class AssertJTest {
@Test
public void learning() {
List<Integers> numbers = Arrays.asList({12, 15, 45});
assertThat(numbers).hasSize(3)
.contains(12, 15)
.allMatch(x -> x > 10)
.allMatch(x -> x < 100)
.noneMatch(x -> x < 0);
assertThat("").isEmpty;
assertThat("ABCDE").contains("BCD")
.startsWith("ABC")
.endsWith(""CDE);
}
}

numbers is a list of integers that contains 3 values as shown. AssertJ provides the method assertThat(), which allows you to chain together multiple assertions.

Interestingly, you can see that the method allMatch() accepts a lambda expression to test the truth value of a predicate. The call allMatch(x -> x > 10) checks whether all the integers within numbers match the predicate of being greater than 10.

assertThat() also works with strings, and works well especially with alphabetical text. The code is there for you to see.

Hamcrest

Hamcrest provides an alternative to AssertJ to write great asserts.

public class HamcrestMatchersTest {
public void learning() {
List<Integer> numbers = Arrays.asList({12, 15, 45});
assertThat(numbers, hasSize(3));
assertThat(numbers, hasItems(12, 15));
assertThat(numbers, everyItem(greaterThan(10)));
assertThat(numbers, everyItem(lessThan(100)));
assertThat("", isEmptyString());
assertThat("ABCDE", containsString("BCD"));
assertThat("ABCDE", startsWith("ABC"));
assertThat("ABCDE", endsWith("CDE"));
}
}
Using Spring Unit

Typical applications have multiple layers and you want to write unit tests for different layers — web, business, and data.

Here are some of the recommended options:

  • Web layer — Spring MockMVC
  • Data layer — DataJpaTest
  • Business layer — Mockito-based test preferably without launching a Spring Context

Unit Tests for the Web Layer

Have a look at the following code:

@RunWith(SpringRunner.class)
@WebMvcTest(ItemController.class)
public class ItemControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private ItemBusinessService businessService;
@test
public void dummyItem_basic throws Exception {
RequestBuilder request = MockMvcRequestBuilders
.get("/dummy-item")
.accept(MediaType.APPLICATION_JSON);
MvcResult result = mockMvc.perform(request)
.andExpect(status().isOk())
.andExpect(content()
.json("{\"id\":1, \"name\":\"Ball\"
, \"price\":10, \"quantity\":5}"))
.andReturn();
//JSONAssert.assertEquals(expected, result.getResponse.getContentAsString(), flase);
}
}

This unit test uses the Spring Unit framework and the Spring MockMVC framework.

We are launching a Spring context and wiring ItemController to use a mock for ItemBusinessService.

Spring MockMVC framework makes it easy to perform REST API requests. In the code above, we are using it to execute a REST API and then setting certain expectations of the result:

  • The URL is /dummy-item
  • The accepted content type is application+json
  • After the request has been sent, check that the response status is "OK", and the content is a JSON object with certain data

It is also possible for us to mock the business service:

@Test
public void retrieveAllItems_basic() throws Exception {
when(businessService.retrieveAllItems()).thenReturn(
Arrays.asList(new Item(2, "Item2", 10, 10)
, new Item(3, "Item3", 20, 20)));
RequestBuilder request = MockMvcRequestBuilders
.get("/all-items-from-database")
.accept(MediaType.APPLICATION_JSON);
MvcResult result = mockMvc.perform(request)
.andExpect(status().isOk())
.andExpect(content()
.json("[{\"id\":3, \"name\":\"Item3\"
, \"price\":20}]"))
,{\"id\":2, \"name\":\"Item2\"
, \"price\":10}]")
.andReturn();
}

When retrieveAllItems() is called on businessService, it is made to return the fixed list of items shown. Once again, we execute a request to a different URL, and when the response comes in, the content is verified to be the proper JSON type with the expected data.

Unit Tests for the Data Layer

DataJpaTest can be used during unit testing of the data layer in a Spring-based enterprise application. DataJpaTest uses an in-memory database for the unit test, by default.

@RunWith(SpringRunner.class)
@DataJpaTest
public class ItemRepositoryTest {
@Autowired
private ItemRepository repository;
@Test
public void testFindAll() {
List<Item> items = repository.findAll();
assertEquals(3, items.size());
}
@Test
public void testFindOne() {
Item item = repository.findById(10001).get();
assertEquals("Item1", item.getName());
}
}
Asserting JSON Responses — JSONAssert/JSONPath

Almost all REST APIs use JSON. How do you assert JSON Content?

Using JSONAssert

Have a look at the following test code:

actualResponse is the content that is returned by a service.

JSONAssert allows us to check specific parts of the request that we are interested in.

  • Within the test jsonAssert_StrictFalse(), we are only concerned with the id, name, and price, ignoring the quantity.
  • You can also write a test to check without escape characters, as we have done with jsonAssert_WithoutEscapeCharacters(). This is much easier on the eye and can be used to compare with an actual response that contains escape characters. This mode of comparing responses is called Strict False.

You can also do assertions in Strict mode, where you compare all the fields, and in the actual format, they are in. That is what we have done with jsonAssert_StrictFalse_ExactMatchExceptForSpaces().

Using JSONPath

An alternative approach in asserting JSONs is the JSONPath framework. You might want to check for specific aspects of the response, such as three items in the response.

Just as XPath is used to query XML, JSONPath is used to query JSON.

  • The expression $.length() returns the number of elements. An assertion can then be used on that returned value.
  • You can check for all the id fields with $..id and compare them with a list of pre-fixed values.
  • You can extract slices of the element list that is in the response, such as the first element ($.[1]), or the first 2 elements ($.[0:2]).
  • You can query the response to check if a particular field is present : $.[?(@.name == 'Eraser')] or $.[?(@.quantity == 5)].
Summary

In this article, we looked at a wide variety of unit testing frameworks present in the Java world. We started with the basic unit testing framework JUnit, and its alternative, TestNG. We looked at how we can do mocking with Mockito and its alternative, EasyMock. We then had a look at Powermock, which is useful when mocking static methods, private methods, and constructors.

We then had a feel of powerful assertion frameworks such as AsserJ and Hamcrest. Spring Unit framework provides MockMVC as the mocking framework for the web layer and DataJPATest for the data layer. Finally, we explored JSONAssert and JSONPath used to assert JSON responses in a unit test.

Thanks for reading

If you liked this post, share it with all of your programming buddies!

Follow us on Facebook | Twitter

Further reading

JavaScript and Node.js Testing Best Practices

An Introduction to Unit Testing in Angular

How to set up and run visual testing with Percy