For the best experience, try the new Microsoft Edge browser recommended by Microsoft (version 87 or above) or switch to another browser Google Chrome / Firefox / Safari
OK

Reimagine Unit Testing With Mockito

Alok Gupta, Technical Lead
Mockito-Unit-Testing-Xoriant

Today, software product engineering teams are shifting towards Mockito framework for unit testing due to its reduced costs, time-saving benefit and faster release and go-to-market of products. The reason? Simplify the development of test by mocking external dependencies and implement them in the test code. Are you aware of the concept of ‘Mocking’? Want to know why mocking method is used in software testing by product teams?

In this blog, we will walk you through the following key points - reasons of mocking, testing approach with Mockito, how to support Kotlin, stubbing & verifying behavior, how to mock the final class and execute the test case. We will also go through mock objects, setup dependencies needed and illustrate the mocking behavior and verification through example.

Mocking is a very powerful way to perform unit testing. It allows you to test in isolation without having to worry about all the other classes in your application codebase. For example, say you are trying to isolate a class, which is a single collaborator, Mockito allows you to substitute the real collaborator that would be used in a live production environment with a mock object so you can test the unit's functionality in every possible way.

There are other alternatives also available for Mockito like Easy Mock. However, Mockito is recommended as the tests are readable and cleans the verification errors. It has been rated among the Top 10 Java library by GitHub community.

Why Mocking?

Mocks reduce the complexity of your tests by allowing you to replace objects that deal with external services such as a database or any web service communicating over the network. But what are its benefits?

The first benefit is keeping things local to the machine where the test runs is simpler.

The second benefit is replacing the objects that allows you to easily provide your test with the data for any scenario, data which otherwise might not be available in a database dependency and might need creating.

Introducing mocks into your tests has the potential of speeding up your test execution. This happens when mocks replace real dependencies that are slow either because they are computationally intensive or because they access resources that are external to the test.

Mockito as unit tests coverage allow us to test our code at the most granular level covering business layer and network layer, ensuring that we can find issues very quickly.

The graph below shows the cost of leaking a bug during each phase of the development lifecycle.

graph bug

Bugs that are found and addressed during development are exponentially cheaper to fix than those that make it into the hands of users.

The easiest way to think about this is that as you progress towards the right side of the graph or further down the development lifecycle, additional roles and skill sets become involved in locating, debugging, and resolving a bug. The earlier the bug is detected; the less effort is needed.

The graph also highlights both the complexity of each testing type, as well as the relative volume that we should be creating of each of them.

So, having exhaustive unit testing coverage metric allows your software product engineering teams to confirm that you have not introduced any breaking changes, it also helps to detect bugs before your users do. It basically cut our testing time down 10x or more. The longer it takes for a bug to be found, the more expensive it is to address.

Testing Approach With Mockito

Let us add the dependencies needed to have basic setup ready for Mockito.

Add below settings in build.gradle of your application.

Dependencies {

                testImplementation “org.mockito:mockito-inline:3.4.6”

}

Once the above dependency is added, you will be prompted to sync the project.

How to Support Kotlin?

To use Mockito in Kotlin, we can use mockitokotlin2 lib.

Add below settings to your build.gradle

Dependencies {

                testImplementation “com.nhaarman.mockitokotlin2:Mockito-kotlin:2.2.0”

}

Stubbing & Verifying Behavior Using Mockito

Xoriant-Mockito-Stubbing-Verifying

Stubbing Using Mock Methods (when.thenReturn || doReturn.when)

Below we have “doReturn” method which describes what the mock will do when this method is called with below precise parameters.

doReturn(loginResponse).when(mockDataManager).doServerLoginApiCall(loginRequest);

We can also use when(mockMethod).thenReturn(mockObject)

when(mockDataManager.doServerLoginApiCall(loginRequest)).thenReturn(loginResponse);

Stub Methods With Exceptions:

This is particularly useful when you want to make sure that your application source code deals with problems either expected or unexpected in the desired way.

doThrow(NullPointerException()).when(mockDataManager.doServerLoginApiCall(loginRequest));

Verify Mock Behavior:

The main aim of the behavior-based testing style is verifying that the unit under test calls certain methods of its collaborators correctly. This way we can ensure that line of code we wanted to cover are covered and the behavior expected is exhibited by unit test.

verify(loginCallback).openMainActivity()

How to Mock Final Class/Method?

1. Create a file named mockito-extensions under /test/resources directory.

2. Add mock-maker-inline as text in the mockito-extensions file

Execute Test Case:

Xoriant-Mockito-Execute-Test-Cases

Way Forward With Mockito Unit Testing

The foundation for any good software testing strategy is unit tests. These tests are easy to write and maintain, cover a very narrow and very specific piece of functionality, and your engineering teams should have a lot of them. The official Android guidelines recommend that about 70% of your automated tests are unit tests.

The next level of testing is integration testing, which is where a test validates the interactions between two areas of responsibility. For example, in a unit test, you may have mocked out a repository you use to connect to a database; whereas, in an integration test, you might implement the repository with an in‑memory database implementation to test a larger portion of the flow. These tests should represent about 20% of your automated tests.

Finally, there are end‑to‑end tests, which should make up only 10% of your tests.

Ensure Digital Quality Assurance With Xoriant Specialized Quality Engineering

Xoriant specialized quality engineering (SQE) methodologies can accelerate product development, digital quality assurance (DQA), and customer experience initiatives. Organizations are enabling end-to-end quality engineering and benefiting greatly by embracing DQA. Via specialized skills and modern tools, DQA helps teams execute the expanded scope of interoperability and test applications across emerging tech cases.

Want to set the stage for a robust Digital Quality Assurance for your software engineering teams?

Connect With Xoriant Product Engineering Experts

Leave a reply

Your email address will not be published. Required fields are marked*

Filtered HTML

  • Web page addresses and email addresses turn into links automatically.
  • Allowed HTML tags: <a href hreflang> <p> <span> <div> <h1> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id> <hr> <br> <br /> <ul type> <ol start type> <li> <dl> <dt> <dd> <em> <b> <u> <i> <strong> <del> <ins> <sub> <sup> <quote> <blockquote cite> <pre> <address> <code> <strike> <caption>
  • Lines and paragraphs break automatically.