Imbibing the Fluency of Mockito

I recently found myself writing some code to integrate two disparate platforms. One of these systems is Java based and the other, while not written in Java, offers a Java API. I’ll call these systems Foo and Bar, respectively.Mockito

It became obvious before I had written a line of code, however, that testing the eventual adapter would require I explicitly mock the later system’s API (i.e. Foo’s) as all I had to go with was a jar file whose classes and methods made it clear they communicated with a live instance.

I spent a few cycles to see what’s new in the world of Java mocking and I was pleased to see that my old friend Mockito is still active and is indeed, still an excellent tool for general purpose mocking. For the uninitiated, Mockito is Java based mocking framework that:

…tastes really good. It lets you write beautiful tests with [a] clean & simple API. Mockito doesn’t give you hangover because the tests are very readable and they produce clean verification errors.

Google code mockito project page - Why Drink It?

Indeed, Mockito offers a simple, fluent API that allows you to precisely mock behaviors without a lot of fuss. For instance, the main facade to interface with Bar is via a QTP class that has methods like logIn, logOut, etc. Rather than relying on classes under test to actually invoke these methods, I can easily create mock instances of QTP with Mockito like so:

Mocking an instance of QTP

QTP qtpThing = mock(QTP.class);

Where mock is a statically imported method from org.mockito.Mockito. With a mock instance, I can then dictate how I wish certain methods to behave, provided I pass along this mocked instance to my classes under test.

For example, the method logIn doesn’t return anything; in fact, one must invoke that method first and then call another method to generate a ticket (or token), which will be used on subsequent method invocations. Thus, the adapter that I’m writing will receive some input values (from Foo in the form of XML) and the adapter will return a ticket (in the form of an XML document as per Foo’s required XML schema).

Accordingly, the test this interaction, I need to do two things:

  • ensure that the logIn method was invoked with specific parameters
  • mock the response of a valid ticket, via the getTicket method

What’s more, I’d also like to verify that a logIn failure results in a particular interaction from within my adapter code. Therefore, I’ll need to mock out some exceptional behavior as well.

In the case of mocking out a particular method, you simply chain together a few methods; in my case, when and thenReturn do the trick like so:

Mocking the behavior of getTicket

when(qtpThing.getTicket()).thenReturn("test-ticket");

In the code above, when the getTicket method is invoked on my mock instance, the String “test-ticket” will be returned.

Next, to ensure that logIn was invoked with parameters obtained from an incoming XML document, I can use Mockito’s verify method.

Using Mockito’s verify to ensure proper interaction

verify(qtpThing, times(1)).logIn("some_value", "some_user_name", "password");

In this case, the verify method checks that logIn is invoked one time and that three particular String values are passed in. If these expectations are not met, Mockito will throw an exception (and your corresponding test case will fail).

Thus, my test case for verifying my adapter is quite simple, yet highly readable.

JUnit test case for verifying logIn behavior

@Test
public void testLoginRequest() throws Exception {
  QTP qtpThing = mock(QTP.class);
  when(qtpThing.getTicket()).thenReturn("test-ticket");
  AdapterRequest request = new AdapterRequest(XML.read("etc/test-login-req.xml"));
  QbosAdapter adapter = new QbosAdapter();
  adapter.setQtpInstance(qtpThing);
  AdapterResponse adapterResponse = adapter.performAction(request);
  assertNotNull(adapterResponse);
  verify(qtpThing, times(1)).logIn("some_value", "some_user_name", "password");
  assertEquals("test-ticket", adapterResponse.getData().getText());
}

What if I need to simulate an exception thrown by the QTP object, ostensibly from an invalid parameter or incorrect credentials during a log in? Again, Mockito’s fluent API makes this a breeze.

In my case, I’d like the logIn method to throw one of the checked methods in its method signature named UnknownQtpException. You can do this via the doThrow and when methods.

Mocking out exceptions in Mockito

doThrow(new UnknownQtpException()).when(qtpThing).logIn("", "blah", "blah");

In the code above, I’m explicitly declaring that if the first parameter to the logIn command is blank, then my mocked QTP instance should throw UnknownQtpException. Putting everything together yields the following test case:

Testing exceptional circumstances with JUnit & Mockito

@Test
public void testFailureLoginRequest() throws Exception {
  QTP qtpThing = mock(QTP.class);
  doThrow(new UnknownQtpException()).when(qtpThing).logIn("", "blah", "blah");
  XML xml = XML.read("etc/test-login-req-err.xml");
  AdapterRequest request = new AdapterRequest(xml);
  QbosAdapter adapter = new QbosAdapter();
  adapter.setQtpInstance(qtpThing);
  AdapterResponse adapterResponse = adapter.performAction(request);
  assertNotNull(adapterResponse);
  verify(qtpThing, times(1)).logIn("", "blah", "blah");
  assertEquals("FAILURE", adapterResponse.getData().getText());
}

The beauty, of course, is that my test cases effectively test my adapter code without relying on a third party system (in this case, Bar). This is naturally a time honored testing technique employable in any language with a mocking framework worth its salt!

If you find yourself writing some integration code in Java, then I can’t recommend Mockito enough. Mockito’s API is quite straightforward and it makes tests easy to comprehend. I mean, it makes tests easy to imbibe. Dig it?
 

Reference: Imbibing the Fluency of Mockito from our JCG partner Andrew Glover at the The Disco Blog blog.
Related Whitepaper:

Bulletproof Java Code: A Practical Strategy for Developing Functional, Reliable, and Secure Java Code

Use Java? If you do, you know that Java software can be used to drive application logic of Web services or Web applications. Perhaps you use it for desktop applications? Or, embedded devices? Whatever your use of Java code, functional errors are the enemy!

To combat this enemy, your team might already perform functional testing. Even so, you're taking significant risks if you have not yet implemented a comprehensive team-wide quality management strategy. Such a strategy alleviates reliability, security, and performance problems to ensure that your code is free of functionality errors.Read this article to learn about this simple four-step strategy that is proven to make Java code more reliable, more secure, and easier to maintain.

Get it Now!  

4 Responses to "Imbibing the Fluency of Mockito"

  1. Bart says:

    Good post. Interesting to see that you actually prefer Mockito for test doubles in Java and find the tests clean. Personally I don’t really enjoy Mockito much. Last week i wrote about that on my blog: http://blog.thesoftwarecraft.com/2013/07/mockito.html.

    For what it’s worth, in the case at hand, wouldn’t you prefer a simulator for the external system rather than mocks and stubs?

    • Hi Bart – if a simulator were available + automate-able from within Java, etc, I would surely give it a try. Alas, that isn’t an option w/this 3rd party service and I’d rather spend the time mocking than in implementing my own simulator.

  2. arezoo says:

    Hi,very thanks
    Iran_urmiya

  3. arezoo says:

    Thanks
    Iran

Leave a Reply


6 − three =



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.

Sign up for our Newsletter

15,153 insiders are already enjoying weekly updates and complimentary whitepapers! Join them now to gain exclusive access to the latest news in the Java world, as well as insights about Android, Scala, Groovy and other related technologies.

As an extra bonus, by joining you will get our brand new e-books, published by Java Code Geeks and their JCG partners for your reading pleasure! Enter your info and stay on top of things,

  • Fresh trends
  • Cases and examples
  • Research and insights
  • Two complimentary e-books
Get tutored by the Geeks! JCG Academy is a fact... Join Now
Hello. Add your message here.