Unit Testing and Mock Testing With JUnit Testing and Mockito Blog
March 26, 2013

Mock and Unit Testing With TestNG, JUnit and Mockito

Java Testing
Java Tools

Unit tests let developers internally control the functionality and compatibility of their applications when they made changes to features, code or the environment. Believe it or not, unit testing is actually a controversial topic among Java developers. Some think that writing unit tests is a waste of time, while others consider them an essential part of the software development process, and the way to ensure that your new app doesn’t, well, suck because it wasn’t checked properly.

And yet some developers are bored by the topic of unit tests. But comparisons between tools like JUnit vs TestNg prove to be popular despite this apparent boredom.

What is Unit Testing?

Each time you enter your car and start it up, you take a look at the instrument panel/dashboard, almost automatically. even older cars are equipped with warning lights, some less serious (like that you need to fill gas), some more serious (like the battery status) and some highly critical (like the engine-is-gonna-explode warning light).

So if you see something wrong, like the "check engine" light is flashing an angry red warning, it probably wouldn't be wise to start driving away. in a similar manner unit tests act as warning signals that something does not work as expected. it wouldn't be wise to deploy code into production when all your unit tests are failing.

But unit tests are just that, early warnings and internal checks that your code does what is expected.

If you really, really know what you are doing, then you might disregard some of them. But this is not the normal case. And like the car analogy, your car without any warning might suddenly stop working (for reasons not detected by the status lights), just like how code that passes all unit tests is not necessarily 100% correct. Before we get into the blood and guts of the report, let’s review a very brief list of points to remember:

  • Unit tests are code themselves (so they might also have bugs, ha!).
  • Unit tests perform a small task and then verify that the result is the expected one.
  • Unit tests that are failing are a warning signal that something is wrong with the expectations of the system.
  • Unit tests that pass do not guarantee 100% correctness of the code.
  • Unit tests should be updated if your requirements change. 

PART I
PART II
PART III
PART IV
TOO LONG, DIDN’T READ

PART I: JUnit vs. TestNG

JUnit is one of the most popular testing frameworks available, and TestNG brings some more advanced enterprise features to your ongoing efforts to keep your code clean, testable and verifiable at all stages of application development and deployment.

If you’ve heard anything about unit tests in Java before, then you’ll know that the de facto testing framework is JUnit, so most of our examples will use it and the major Java ides (i.e. eclipse, intelliJ idea, netBeans) have explicit support for it.

JUnit is a port to Java from the original SUnit from Smalltalk created by Kent Beck. Since then similar libraries exist for other language as well such as nunit, phpunit, Cunit. Here is a comprehensive list of other testing frameworks.

TestNG (test next generation) is another framework for Java, which can be seen as a more advanced JUnit. it is also possible to use other test frameworks for languages that run on the JvM to test Java code. Spock which is the test framework of Groovy can be used to test Java and Groovy code.

Note: unfortunately, we have limited space in this report, so we’ll ask you to view certain parts of this content on the Zeroturnaround blog. The following parts appear in Why Your Next Cloud App will Probably Suck Without....Unit Testing:

  • Get started by setting up a “hello world!” unit test, will all the code you need to make it happen.
  • Seeing your unit tests from the end-user perspective, driven by the features required.
  • Unit testing as a warning signal for later (i.e. what happens we a new dev joins your team in 2 years and starts playing with legacy code?)

However, let’s continue with some more advanced stuff for those of you who already checked out the blog. Please note that, unfortunately, some code snippets are too long to fit in one column, and therefore carry over to the next. We are planning a fix for this in the future, apologize for this inconvenience.


JUnit Setup and Tear-Down

After you have written your first JUnit class you might think that unit testing is a tedious process that deals with large amounts of low level code. The reality is however the JUnit (and more extensively TestNG) have several features that make your life easier.

Assume that you have already implemented a class that checks the validity for urLs called Myurivalidator. The class needs several statements to set up correctly. So your first attempt for a unit test might be:


public class MyUriValidatorTest {  

     @Test  
     public void test1() {
          MyUriValidator myValidator = new MyUriValidator();
          myValidator.allowFileUrls(true);
          myValidator.allowInternationlizedDomains(false);
          myValidator.allowReservedDomains(false);
          myValidator.allowCustomPorts(true);

          assertTrue("Domain is valid",myValidator.isValidUrl("http://www.google.com"));  }

     @Test  
     public void test2() {    
          MyUriValidator myValidator = new MyUriValidator();
          myValidator.allowFileUrls(true);
          myValidator.allowInternationlizedDomains(false);
          myValidator.allowReservedDomains(false);
          myValidator.allowCustomPorts(true);

          assertTrue("Domain is valid",myValidator.isValidUrl("file://home/users"));  
     }

     @Test  
     public void test3() {
          MyUriValidator myValidator = new MyUriValidator();     
          myValidator.allowFileUrls(true);
          myValidator.allowInternationlizedDomains(false);
          myValidator.allowReservedDomains(false);
          myValidator.allowCustomPorts(true);    

          assertFalse("Domain is invalid",myValidator. isValidUrl("http://localhost:8080/"));  
     }


There is clearly a lot of code duplication here. JUnit has a @Before annotation for code that runs automatically before each test method. So your test can be simplified to:


public class MyUriValidatorTest {
     private MyUriValidator myValidator = null;

     @Before
     public void beforeEachTest() { //Name of method does not actually matter
          myValidator = new MyUriValidator();
          myValidator.allowFileUrls(true);
          myValidator.allowInternationlizedDomains(false);
          myValidator.allowReservedDomains(false);
          myValidator.allowCustomPorts(true);  
     }

     @Test
     public void test1() {
          assertTrue("Domain is valid",
               myValidator.isValidUrl("http://www.google.com"));

     }

     @Test
     public void test2() {
          assertTrue("Domain is valid",      
               myValidator.isValidUrl("file://home/users"));   
     }

     @Test  
     public void test3() {
          assertFalse("Domain is invalid",
               myValidator.isValidUrl("http://localhost:8080/")); 
     }
}


There is also the respective @After annotation (runs after each test), as well as @Beforeclass and @Afterclass annotations for code that runs onCe before/after all tests.

You use the @After annotation to clear up resources requested in the @Before. Here is an example for an integration test where a database connection is created in the beginning and released in the end for each test.


import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class SimpleDatabaseTest {

     private MyDbConnection myDbConnection= null;

     @Before
     public void dbSetup()
     {    
          // Will actually run twice (for test1 and test2)
          System.out.println("Preparing db Connection");
          myDbConnection = new MyDbConnection();
          myDbConnection.connect();
     }

     @After
     public void dbTearDown()
     {
          // Will actually run twice (for test1 and test2)
          System.out.println("Cleaning up");
          myDbConnection.releaseConnection();
     }

     @Test
     public void test1() 
     {
          System.out.println("Test 1 runs");
          myDbConnection.doSomethingElseWithDb();
          //Assert statements should be here for this test to be complete
     }

     @Test
     public void test2() {
          System.out.println("Test 2 runs");
          myDbConnection.doSomethingElseWithDb();    
          //Assert statements should be here for this test to be complete}}

 


If you run this test it will print the following (broken due to space issues):

Preparing db ConnectionTest 2 runs
Cleaning upPreparing db Connection
Test 1 runsCleaning up

The @Beforeclass and @Afterclass can be used for expensive objects that need to be created only once. Be careful however with state changes. Your unit tests should be self-contained and with no side effects. This lets them remain completely independent so that you can run them in any order (or even in parallel).

Here is an example where an expensive object (an earthquake simulation module) is created only once during the tests:


import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

public class EarthQuakeTest {
     private static EarthQuakeSimulator earthQuakeSimulator = null;

     @BeforeClass
     public static void prepareSimulation() {
          // Will run only once regardless the number of tests
          System.out.println("Preparing earthquakesimulation");

          earthQuakeSimulator = new EarthQuakeSimulator();
          earthQuakeSimulator.startup();    
     }    

     @AfterClass    
     public static void endSimulation() {
          // Will run only once regardless the number of tests
          System.out.println("Cleaning up");
          earthQuakeSimulator.shutdown();    
     }

     @Test
     public void test1() {
          System.out.println("Test 1 runs");
          earthQuakeSimulator.simulateEarthQuakeInAsia();
          earthQuakeSimulator.resetEarthToInitialState();
          // Assert statements should be here for this test to be complete    
     }

     @Test
     public void test2() {
          System.out.println("Test 2 runs");
          earthQuakeSimulator.simulateEarthQuakeInAsia();
          earthQuakeSimulator.resetEarthToInitialState();
          // Assert statements should be here for this test to be complete
     }
}


Notice that the annotated methods for @Beforeclass and @Afterclass are declared static (this is a limitation of JUnit, but TestNG is more flexible). If you run this unit test you will get:

Preparing earthquake simulation
Test 1 runs
Test 2 runs
Cleaning up

These annotations are also very useful when you use a specific helper for a test (e.g an integration framework or an in-memory database) that you want to use for all your tests.


JUnit Parameterized Tests

So with the help of the @Before annotations we have much less code duplication. Continuing with the example of the MyUrlValidator we still see that we have to create a new method each time a new urL needs to be tested. JUnit supports parameterised tests where you write a general test method once, then a separate method provides the data.

Here is the approach for that:


@RunWith(Parameterized.class)
public class MyUriValidatorTest {

     private MyUriValidator myValidator = null;
     private String uriTestedNow =null;
     private boolean expectedResult = false;
     public MyUriValidatorTest(String uriTestedNow,boolean expectedResult)
     {
          this.uriTestedNow = uriTestedNow;
          this.expectedResult = expectedResult;
     }    

     @Parameters    
     public static Collection data() { 
     /* First element is the URI, second is the expected result */
     List uriToBeTested = Arrays.asList(new Object[]
[] {
               { "http://www.google.com",true },            
               { "file://home/users", true },
               { "http://staging:8080/sample", true },
               {"http://localhost:8080/", false } });

     return uriToBeTested;    }

     @Before
     public void beforeEachTest() {
     myvalidator = new MyUriValidator();
     myValidator.allowFileUrls(true);
     myValidator.allowInternationlizedDomains(false);
     myValidator.allowReservedDomains(false);
     myValidator.allowCustomPorts(true);    
     
     }

     @Test
     public void testCurrent() {
          assertEquals("Testing for "+uriTestedNow,expectedResult,myValidator.isValidUrl(uriTestedNow));    
     }
}


As you can see, adding a new urL is a single line change in the the method annotated as Parameters.

Exception Testing With JUnit

Occasionally, you might want to verify in your unit test that a method throws some specific exception. Prior to JUnit 4, you might have achieved this by writing a try-catch block inside a test method so that test would pass if the catch block is reached. JUnit 4 provides more elegant way to test such exceptional cases.

Let's assume that the Basketweightcalculator class from the introductory blog post has been changed so that addItem() method will throw IllegalArgumentexception if it gets a negative argument passed to it. How to test it? With JUnit 4 it is nice and clean:


@Test(expected= IllegalArgumentException.class)
public void shouldNotAddNegativeWeights() {
     weightCalculator.addItem(-5);
}


When you need to verify that the thrown exception has a specific message bundled with it, then you could use JUnit's ExpectedException rule. The next sections goes into greater detail on @Rule annotation.

Extending JUnit With Rules

JUnit @Rule annotation allows you to smoothly change or extend the behaviour of your test methods. there are 8 rules provided by the JUnit library: ErrorCollector, ExpectedException, ExternalResource, TemporaryFolder, TestName, TestWatchman, Timeout and Verifier. We are going to cover only few of these in the current section. But what’s cool is that you can extend this list by writing your own rules!

Let's get back to our addItem() method that throws IllegalArgumentException in certain cases. what if we need to check that this exception gets thrown and it has a specific message? With JUnit's ExpectedException rule we could write the test as follows:


@Rule
public ExpectedException thrown = ExpectedException.none();

@Test
public void shouldNotAddNegativeWeights() {
     thrown.expect(IllegalArgumentException.class);
     thrown.expectMessage("Cannot add negative weight");
     weightCalculator.addItem(-5);
}


Another useful and simple-to-use rule is a timeout rule. It sets the timeout in milliseconds for each test method. When some test method takes more time to execute, then this test fails. Let's verify that addItem() method executes in 100 milliseconds:


@Rule
public Timeout timeout = new Timeout(100);

@Test
public void shouldAddItemsQuickly() {
     weightCalculator.addItem(-5);
}

 


Grouping Your Unit Tests With JUnit Categories

The @Category annotation provides a way to divide test methods into groups. For example, to gather all test with similar properties (e.g. slow tests) into one group. One test method can belong to many groups as the following example shows for SecondClassTests.testSomething() test method.


public class FirstClassTests {

@Category(MyGroupA.class)
@Test
public void testSomething() {
     new FirstClass().testSomething();
}

@Category(MyGroupB.class)
@Test
public void testSomethingElse() {
     new FirstClass().testSomethingElse();
     }
}

public class SecondClassTests {

@Category({MyGroupA.class, MyGroupC.class})
@Test
public void testSomething() {
     new SecondClass().testSomething();
     }
}


Next, when we want to run all test methods belonging to group MyGroupA, we need to create a test suite for that.


@RunWith(Categories.class)
@IncludeCategory(MyGroupA.class)
@SuiteClasses( { FirstClassTests.class, SecondClassTests.class})
public class MyGroupATestSuite { }


In order to get it to actually work, we should define each category type (MyGroupA, MyGroupB, MyGroupC) as a Java interface. You can create sub-types and parent-types by extending interfaces.

Multiple Test Arguments With JUnit Theories

When you annotate the test method with @Theory keyword, then JUnit will invoke this method with all possible combinations of variables declared as @DataPoint (or @DataPoints, if you have packed the variables into an array).

For example, when we want to test some method which takes two integers as parameters and we would like to run tests with such set of parameters: { (0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)} then @Theory can help us to keep the code compact.


@RunWith(Theories.class)
public class CombinationTest {

     @DataPoints public static int[] INTS = new int []{0, 1, 2, 3};

     @Theory
     public void testCalculation(int x, int y) {
          Assume.assumeTrue(x < y);
          new Combination().calculate(x, y);
     }
}

 


Utilizing TestNG in Addition to JUnit

TestNG is another testing framework for Java. It is inspired from JUnit and supports a lot more features aimed at development of enterprise Java applications. Some of its features are so successful that have been copied/ ported to JUnit as well. Or some JUnit features seem to draw inspiration for TestNG, if you prefer!

Here is an overview of features supported by TestNG and how they compare to JUnit.

table comparing features supported by JUnit vs TestNG

Some of the most interesting features of TestNG (not offered by JUnit) are:

  • Powerful parameterized tests with data providers that choose input data during run-time
  • Parallel testing of test cases for increased performance
  • Dependencies among test cases and complete control over the order of the tests run

The third capability is very powerful but also needs great attention if you choose to use it. Normally, all your test cases should be completely independent and they should be able to execute in any order. No test should have side effects, and no test should depend on the outcome of another one. But let’s look at the first two features we mentioned above: Parameterized and Parallel testing

Super-Powered Parameterized Tests With TestNG 

While JUnit has basic support for parameterized tests, the approach it follows is not very flexible. As you saw in the MyUrlValidator example, parameters exist as private fields in your test class, and also a special constructor is needed. Wouldn’t it be great to add parameters as arguments into the test method themselves without polluting the test class with extra fields? Of course it would! this is exactly what TestNG does. TestNG introduces the concept of a dataprovider, which is a way to create test data and bind it to test methods. Binding happens via the name of the data provider, and the test data and test code are completely decoupled and you are free to connect them as you want. This offers much more flexibility than JUnit.

Rewriting MyurLvalidator test with TestNG:


import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class MyUriValidatorTest {

     private MyUriValidator myValidator = null;

     @BeforeMethod
     public void beforeEachTest() {
          myValidator = new MyUriValidator();
          myValidator.allowFileUrls(true);
          myValidator.allowInternationlizedDomains(false);
          myValidator.allowReservedDomains(false);
          myValidator.allowCustomPorts(true);
     }

     @DataProvider
     private static final Object[][] createSamples() {
          return new Object[][] { { "http://www.google.com", true },

                    { "file://home/users", true },
                    { "http://localhost:8080/", false } };
     }

     @Test(dataProvider = "createSamples")
     public void test URL(String uriTested, boolean expectedResult) {
          asserEquals(myValidator.isValidUrl(uriTested), expectedREsult,
               "Test for " + uriTested);
     }
}


As you can see, the code is much more compact. Even better is the fact that the data provider and the test method are decoupled, meaning that you can have multiple data providers and many test methods with any combination of binding between them.

With a big number of parameters, error reporting is somewhat lacking in JUnit. JUnit will number each test argument in sequence, giving no direct indication what was the argument. if we create a failed test where only one argument did not pass you get the following:

screenshot of JUnit and TestNG Results

TestNG on the other hand directly reports both the argument and the result so that you can see at a glance where the problem lies. For test cases with a large number of parameters (e.g. hundreds) this can be a huge time saver.

TestNG also supports having the dataProvider and the test method in completely different classes, allowing for even better code reuse.

dataProvider Class Example:


Public class SampleURLStrings {
     @DataProvider
     private static final Object[][] createSamples() {
          return new Object[][] { { "http://www.google.com",true },
               { "file://home/users", true },
               { "http://localhost:8080/", true } };    
     }
}


And here is the unit test that references this dataProvider

@Test(dataProvider = "createSamples", dataProviderClass = SampleURLStrings.class)
     public void testURL(String uriTested, boolean expectedResult){
          assertEquals(myValidator.isValidUrl(uriTested),expectedResult,
               "Test for " + uriTested);
     }

 

In a big enterprise project, it might be very helpful to centralize all test data in a single place for easier management of new requirements that affect those test cases that have yet to be verified.

Parallel Testing with TestNG

Assuming that your tests are written correctly (i.e. they are independent of each other), you have the option to run them in parallel. this speeds up the build in most cases and it’s very handy when your TestNG tests are executed in the build server (e.g. Jenkins) as part of your build process.

TestNG has built-in support for running tests in parallel. It is possible to do this in JUnit as well, but you need external support, like using Maven. In TestNG you just add two more attributes in the testng.xml file of your suite. Here is an example:

&lt;?xml version="1.0" encoding="UTF-8"&gt;
&lt;!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd"&gt;
&lt;suite thread-count="10" name="Suite" parallel="methods" verbose="1"&gt;
  &lt;test name="report-sample"&gt;
    &lt;classes&gt;
      &lt;class name="com.zeroturnaround.quakes.QuakeSimulator"/&gt;
      &lt;class name="com.zeroturnaround.quakes.QuakeSimulator2"/&gt;
    &lt;/classes&gt;
  &lt;/test&gt;
&lt;/suite&gt;


Notice the added “parallel” and thread-count XML properties. These instruct TestNG to use multiple threads for executing the defined tests. The count value defines how many threads to use (i.e. size of thread pool). The parallel value is usually one of the following:

  • methods - this is the most useful option for using parallelism at a fine-grained level
  • classes - Coarse-grained parallelism

Whew! this section was a bit intense. Now that you’ve seen some advanced features of JUnit and TestNG, plus a comparison between the two tools, it’s probably best now to discuss what to test and how. After all, understanding parameterized tests, method rules, categories, theories, and how to do parallel testing without external support from Maven, figuring out where to start with your own tests is the next logical step...


PART II: Figuring Out What to Test

So now that you know what are unit tests, why are they needed and how they can help you as a developer, perhaps you are thinking you are going to test the gigantic enterprise application of your company that contains thousands of lines of code. Where do you start?

Don't Unit Test Everything...

Before writing a single unit test, it’s necessary to determine exactly what to test. A big enterprise application can hold a billion lines of code, so it is realistic to write tests for everything? not exactly. So, it’s important to make sure your tests are focused on what actually matters to you, your app and your users.

Let’s see what you should NOT test and get it out of the way first:

  • Other framework libraries (you should assume they work correctly)
  • The database (you should assume it works correctly when it is available)
  • Other external resources (again you assume they work correctly when available)
  • Really trivial code (like getters and setters, for example)
  • Code that has non-deterministic results (i.e. thread order or random numbers)

What You Should Unit Test

One of the golden rules of unit testing is that your tests should cover code with “business logic”. Here is the typical flow in a back-end processing system. Your web application could look like this:

diagram of typical flow of web app and where to focus testing

In this case, the highlighted part in gold is where you should focus your testing efforts. This is the part of the code where usually most bugs manifest. It is also the part that changes a lot as user requirements change since it is specific to your application.

So what happens if you get across a legacy application with no unit tests? What if the “business logic” part ends up being thousands of lines of code? where do you start?

In this case you should prioritize things a bit and just write tests for the following:

  • Core code that is accessed by a lot of other modules
  • Code that seems to gather a lot of bugs
  • Code that changes by multiple different developers (often to accommodate new requirements)

How much of the code in these areas should we test, you might ask. Well, now that we know which areas to focus on, we can now start to analyze just how much testing we need to feel confident about our code.

Note: Due to space limitations, we’ll kindly ask you to visit the Zeroturnaround blog if you’d like to see more content on Code Coverage, which is a metric that tells you how much of your code is “touched” by your unit testing efforts. We covered this in Don’t Test Blindly: The Right Methods For Unit Testing Your Java Apps.


PART III: Setting Up Mock Alternative Realities 

Unit testing is great to use when you start writing a new application and everything is clean and pristine. But what if you inherit a mess of code inside some huge enterprise application, and everything you need to deal with is already there, and ideally working correctly?

Just when you thought everything was going so well, we throw a monkey wrench into your new unit testing world...because with complex legacy applications, you cannot simply start implementing your own unit tests out of the blue.

For example, if you change something, how can you tell what will be affected? The side effects of your changes should be clear from the beginning, and we do this by Mocking, which lets you create alternative realities for your application to play through, without having any side effects or consequences in reality (kinda like the Truman show :)

Let’s see why using a Mocking framework is better than doing anything by hand, and some of the tools available.

Don't Mock by Hand: Use a Mocking Framework

At RebelLabs we sometimes say that smart + lazy = efficient. So why create a bunch of human-error prone manual tests on-the-fly when you could be so much lazier and use a mocking framework, such as Mockito, easyMock, JMockit and others.

Mocking attempts to solve in an easy way the creation of fake objects that help the unit testing process. Like our comparison to the truman show, mock objects are designed to “fool” a Java object to think that it communicates with other real objects.

From the point of view of the tested class, everything runs normally. It communicates with other objects and gets all the appropriate responses. Behind the scenes however, this is only theater, a mummer’s show if you will, which has been carefully planned by you.

The mock objects within your library allow you to setup a controlled environment with strictly-defined deterministic behaviours by all objects involved with the class in question. I’ve added a visual here as an overview of mocking:

illustration of class in real system vs mocking framwork for unit test

In your new theater, you should use a mocking framework to set the stage, in which you carefully monitor all interactions of the tested class in order to verify its effectiveness. Then you can see if all your “actors” performing properly.

So when should you use mocking?

We suggest using mocking when the class you want to unit test communicates with other classes that have side effects which should only be called in the real production system. Some random examples, with significant side effects in real life, are:

  • Charging a credit card or bank account
  • Printing medical records, invoices, personal documents, etc.
  • Sending an overdue bill notification to a client via email
  • Sending a request to an external system
  • Launching weapons into a neighboring enemy solar system • flooding the reactor core
  • Shutting down life support

Ok, that list is a bit morbid, but you get the point. You can also use mocking in other cases as well. A common practice is to mock some classes that are very slow and based on a lot of dependencies not needed for the unit test. Mocking is also great when you want to emulate strange errors such as a full hard disk, network failure, wrong serialized version etc.

When Not to Use Mocking

Always remember that you should mock the objects that your classes come in contact with, because you are interested in the class itself and nothing else. If you actually want to see the interaction of the whole module then you need integration tests, something we will cover later.

Therefore you should not use mocking when you are interested in:

  • Data that comes from external resources or the dB (e.g. resultsets)
  • Transactions
  • The interaction of your application with your application server or environment • testing multiple modules together as a single component

For all these cases you need integration tests, because we are now looking beyond the classes themselves. If you have several objects that work correctly isolated (because the unit tests pass), this does not mean that they will also work correctly when used together. This is where integration tests come in.


PART IV: Mockito for Advanced Users

In this section we jump right into the heady brew that is Mockito. 

Getting Your Blender Ready for Your First Mocks

Jumping right in, imagine you have a spring web application--take lr-demo-answers-java for example.this is also a Maven project, so to unleash the power of Mockito onto this app we just need to define a couple of test-scope dependencies:


  junit 
  junit
  4.8.2 
  test
 

  org.mockito
  mockito-core
  1.9.5
  test


Mockito logo and testimonial from Kostis Kapelonis

Now we have code to test and whole infrastructure set up, so we can proceed straight to writing some tests and showing off Mockito features:

Screenshot of EmailUniqueValidator.java and EmailUniqueValidatorTest.java files in Mockito Features

Let’s look at emailuniquevalidator, it’s just a normal constraintvalidator which you can think of as a util class that queries some service to base assumptions on the data. There’s nothing special here; it includes a method isvalid, which contains non-trivial logic to test.

We consider this try-catch nontrivial as it swallows exceptions and returns counterintuitively, true if the service is unavailable. What is important to our example is that we call a userservice instance, while pondering the validity of a given email. Mocking a service is what Mockito excels at, so check out a sample test in emailuniquevisitortest. Below we bring up one of its test methods:


import static org.mockito.Mockito.*;
...

@Test
public void testNonUniqueEmailIsNotValid() {
String emailValue = "[email protected]";
UserService userService = mock(UserService.class);
User user = mock(User.class);  
// we expect findByEmail be called when(userService.findByEmail(emailValue)).thenReturn(user);  
boolean valid = new EmailUniqueValidator().setUserService(userService).isValid(emailValue, null);
assertFalse("email is valid despite there's a user with it", valid);
}


Almost all Mockito functionality is available through static methods, which allows us to use static imports and maintain code that is surprisingly clean and readable.

At the end of the test, a very thorough developer can also verify that mock methods have been called appropriately, even Mockito’s official point of view is that this is almost always redundant in simple cases. The explanation is simple: if you don’t properly stub some method that is important, your test will probably fail before the verification. So maybe you shouldn’t stub that method at all!

That is the basic example of mocking your services with Mockito. naturally, there are integrations with frameworks; when you use a dependency injection framework, like Spring in the example above, you want all your beans to be managed automatically.

So there is Springockito, which allows you to annotate your tests and have your mocks injected into their rightful places with almost no interactions.


"classpath:/context.xml")
public class SpringockitoAnnotationsMocksIntegrationTest extends
AbstractJUnit4SpringContextTests {

     @ReplaceWithMock
     @Autowired
     private InnerBean innerBean;
...
}


This small example confirms that Mockito is a very powerful mocking tool and despite the fact that we just touched the tip of this “framework iceberg”, we showed how easy it can be to integrate your project, your existing tests and Mockito.

When Not to Use Mock Testing

Guess what? There are cases when you cannot mock something efficiently, usually in legacy or poorly-designed systems. So your system might not be optimally designed and screams for refactoring, but sometimes there’s no time to do this. And prior to refactoring, it is good practice to cover your code with tests, unless you really like surprises and random bugs (fail!) Userdetailwrapper has one method with logic: getAuthorities().

So imagine that you cannot mock user. That’s when Mockito’s spies come to the rescue. Instead of mocking an object and stubbing its interactions with the environment, a spy wraps the object and delegates method calls to the real instance while providing all the monitoring features of a mock. Taking a look at the userdetailwrappertest, you can see that spies are created from real user instances, and a real user object is called when a wrapper tries to determine its authorities.


@Test
public void getAuthoritiesNoContactUser() {
  // a real object is created and real object method will be called
  User user = spy(new User());
  UserDetailsWrapper wrapper = new
  UserDetailsWrapper(user);
  Collection<? extends GrantedAuthority> authorities = wrapper.getAuthorities();
  assertTrue("User has no contact, but has authorities!", authorities.isEmpty());  verify(user).getFacebookId();  verify(user).getEmail();
  // verify id is not necessary if we have no facebook and no email
  verify(user, never()).getId();
}


However, a spy allows us to verify that the facebook and email getters of the underlying user object were called and id getter wasn’t. Isn’t that great? now you can build and verify your assumptions of what the system is doing without modifying its functionality.

That was kind of easy: the real User instance didn’t do anything important, but when we have a complex system component coming from the outside, initialized and non-mockable, these Mockito spies are saviors!


@Test
public void normalUserHasAuthorities() {
  // a real object is created and a real object method will be called
  User realInstance = getComplexInitializedUser();
  User user = spy(realInstance);
  UserDetailsWrapper wrapper = new 
  UserDetailsWrapper(user);
  Collection<? extends GrantedAuthority> authorities = wrapper.getAuthorities();
  verify(user).getFacebookId();
  verify(user).getEmail();
  verify(user).getId();
  assertTrue("User has no id, but has authorities!", !authorities.isEmpty() && authorities.
  iterator().next().getAuthority().equals(StandardAuthorities.USER));
}
private User getComplexInitializedUser() {
  User user = new User();
  user.setId(1L);
  user.setEmail("[email protected]");
  return user;
}


Above, we can see that a user comes with a state and is initialized and ready. Still we are able to peek at the wrapper functionality flow and verify the return values and the underlying component usage.

Now spies offer little added value compared to mocks when a system has a nice, testable design, but when its is something you don’t want to look at design wise, they are really handy. Just don’t allow them to get you too deep and start testing objects you’re spying on.


Working With Ranges of Values: Argument Matchers and Captors

Two other features that allow you an even more fine-grained verification of the things happening to the objects you test are argument matchers and captors.

The argument matcher concept is quite straightforward: instead of specifying an exact value of the argument, like we did in the emailuniquevalidatortest, we can specify a range of the arguments.


Matchers.any(Class clazz) // any object or null, clazz is used to avoid casting
Matchers.anyInt() // any int
Matchers.anyString() // any value of String


The methods above allow us to conveniently specify a range of possible values to the stubbed method. We could have rewritten testuniqueemailIsvalid using them like shown here.


@RunWith(MockitoJUnitRunner.class)
public class EmailUniqueValidatorTest extends TestCase {
private EmailUniqueValidator validator;
private UserService service;
@Before
public void initialize(){
  UserService userService = mock(UserService.class);
  User user = mock(User.class);
  when(userService.findByEmail(anyString())).thenReturn(user);
  this.service = userService;
  this.validator = new EmailUniqueValidator().setUserService(service);
}
@After
public void verifyServiceCall() {
  verify(service).findByEmail(anyString());
}
@Test
public void testNonUniqueEmailIsNotValid() {
  boolean valid = validator.isValid("anything", null);
  assertFalse("email is valid despite there's a user with it", valid);
  }
}


As you see, we do not restrict stubbing method calls to a specific email. This is especially useful, when you want to prepare your mocks for the whole test case, not just for a single test. After every test we make sure that our mock was indeed useful and was called with some string parameter.

So while argument matchers provide a convenient way to increase the range of accepted arguments, captors serve the opposite goal. With an argument captor, you can verify arguments that were given during the test execution. Look at the emailuniquevalidatortestMatchers, we use a captor to ensure that the argument given to the underlying service is in fact a specific value.


@Before
public void initialize(){
  UserService userService = mock(UserService.class);
  User user = mock(User.class);
  this.captor = ArgumentCaptor.forClass(String.class);
  when(userService.findByEmail(captor.capture())).thenReturn(user);

 

Verifying Order of Calls

The last feature that we want to cover is execution order verification. It is a very straightforward, but powerful concept that lets you run a verification of certain method calls happening in an appropriate order.

For example, you want to fetch a record from the database first and then check its data, not the other way around. Mockito offers you an Inorder interface.


import static org.mockito.Mockito.inOrder;
...
public void verifyDatabaseInteractions() {
  InOrder inOrder =inOrder(daoMock);
  inOrder.verify(daoMock).fetch(recordId);
  inOrder.verify(daoMock).validateData(record);
}
  this.service = userService;
  this.validator = new EmailUniqueValidator().setUserService(service);
}
@After
public void verifyServiceCall() {
  verify(service).findByEmail(anyString());
  assertTrue(message.equals(captor.getValue()));
}


The most useful thing about the captors approach is that you don’t need to provide a valid value to verify, but you extract the value and can validate it in a procedure more complex than a simple comparison.

This example shows a piece of code that does exactly that, first daoMock should fetch, then validatedata. If those methods were called in any other order, the test will not pass.

Simply put, Mockito is a very rich framework and offers many useful features, and when you are armed with the ones we showed above, you can build readable tests for systems of any complexity. Have fun!


Conclusion on Mock and Unit Testing

We covered a lot of topics in this report in the context of unit testing and we hoped that you got some pointers on the tools available and the capabilities they offer. For those of you who didn’t have time to really delve into it all, here’s a quick sum up:

  • Keeping Your Code Safe with Unit Testing introduced the concept of unit testing and the reasons why you and your development team should be using these methods and tools.
  • JUnit and TestNG for Advanced Guru-Types (deep breath!) covers JUnit setup and tear-down, parameterized tests, exception testing, method rules, categories, theories, test ng feature comparison with JUnit, super-powered parameterized tests with TestNG and parallel testing without external support.
  • Figuring out whAt to test helps you figure out what NOT to test (like your own database!) and where you should focus your efforts instead.
  • Setting up Mock Alternate Realities helps you know when to, and when not to, use a mocking framework, like Mockito, easyMock and JMockit, to virtually test commands that could have serious ramifications if actually carried out in the real world (i.e. print all 50M customer invoices!)
  • Mockito for Advanced Users (woohoo!) reviews how to create your first mocks, why mocking with poorly designed or legacy systems can give you headaches, a bit about argument matchers, captors and execution order verification.

Geeky Comic

To conclude, it’s pretty clear that unit testing with JUnit, TestNG and Mockito brings tangible benefits: a cleaner, better code base, greater involvement and understanding of the code on behalf of your development and a focus on the “big picture” all helps you build and release future versions of your apps much better.

And before we sign off for now, here is some food for thought: How would you integrate your unit tests in the build process so that the build itself fails when a test fails? Hint: we already mentioned “Integration Tests” in this report, but for more on that stay tuned!


Now, what are the right methods for unit testing in Java? Read our blog and find out.

Read the Article