Chapter 2. Socializing with Mockito

"The significant problems that exist in the world today cannot be solved by the level of thinking that created them."

– Albert Einstein

This chapter distills the Mockito framework to its main core and provides technical examples. No previous knowledge of Mocking is necessary.

The following topics are covered in this chapter:

  • Exploring Mockito
  • Working with Mockito
  • Understanding the Mockito architecture

The Exploring Mockito section covers the unit test qualities and significance of Mockito in unit testing.

The Working with Mockito section explicates the Mockito framework and covers the following topics:

  • Stubbing method calls
  • Verifying method invocation
  • Matching arguments
  • Answering method calls

The Understanding the Mockito architecture section explains the internal architecture of Mockito.

Exploring Mockito

Mockito is an open source mocking framework for Java. Mockito comes under the MIT license. The MIT license says that anybody can use the software free of charge and can use, copy, modify, merge, publish, distribute, and sell the software.

In Chapter 1, Exploring Test Doubles, we read about test doubles, spies, stubs, and mock objects. Test doubles replicate the external dependencies so that the code under test can interact with its external dependencies and allow you to isolate code from its dependencies to test them on a standalone basis. Mockito streamlines the creation and management of external dependencies and allows mock object creation, verification, stubbing, and spying on real objects. To learn more about Mockito, visit the following links:

Exploring unit test qualities

Writing clean, readable, and maintainable unit test cases (JUnit, TestNG) is an art; just like writing clean code. A well-written unit test can prevent maintenance nightmare and acts as a form of system documentation, but if not used carefully, it may produce meaningless boilerplate test cases.

Unit tests should adhere to a number of principles for readability, flexibility, and maintainability. This section elucidates the principles that we'll follow throughout this journey. The following are the principles:

  • Should be reliable: A unit test should fail if, and only if, the production code is broken. If your test starts failing for some other reason, for example, if the database server is down or Internet connection is not available, it implies that your code is broken. However, in reality, your test is failing because of an external resource that is not a part of your code.
  • Unit tests should be automated: The following are the benefits of test automation:
    • Assumptions are continually verified: We refactor code (change the internal structure of the code without affecting the output of the system) to improve code quality in terms of maintainability, readability, or extensibility. We can refactor code with confidence if automated unit tests are running and giving feedback. We should not refactor code without proper test coverage.
    • Side effects are detected immediately: This is useful for a fragile, tightly-coupled system when a change in one module breaks another module.
    • Saves time with no need for immediate manual regression testing: If you are adding a scientific computation behavior to an existing calculator program and modifying the code, you need to do a regression to verify the integrity of the system after every piece of change. Regression testing is tedious and time consuming, but if you have an automated unit test suite, you can delay the regression testing until the functionality is done. This is because the automated suite will inform you at every stage if you break an existing feature.
  • Tests should be executed extremely fast: This is because the tests can provide quick feedback. A test should not take more than a second to finish the execution. Your application can have thousands of tests. If they take hours to finish, every change you commit will have to wait for an hour to get the feedback, which is not acceptable.
  • Trouble-free setup and run: Test setup should be simple. Unit tests should not require a DB connection or an Internet connection or delete a temp directory.

Mockito provides APIs to mock out the external dependencies and achieve the qualities mentioned here.

Realizing the significance of Mockito

Automated tests are a safety net. They run and notify if the system is broken so that the offending code can be fixed very quickly. If a test suite runs for an hour, the purpose of quick feedback is compromised.

Consider a development environment where every line of code changes (commits to the source control, for example, Git, SVN, or Rational ClearCase), triggers an automated test suite, and takes hours to complete. A developer has to wait for an hour or more to verify a new change until the test run is complete. This blocks the progress of the development.

A test may take time to execute or fail needlessly when your code exhibits testing-unfriendly behaviors or interacts with testing-unfriendly external objects.

The following are examples of testing-unfriendly behaviors:

  • Acquiring a database connection and fetching/updating data
  • Connecting to the Internet and downloading files
  • Interacting with an SMTP server to send an e-mail
  • Looking up JNDI objects
  • Invoking a web service
  • Performing I/O operations, such as printing a report

Do we really need a database connection or Internet connectivity to unit test a piece of code?

If the connection to a database is not possible or the stock price cannot be downloaded, the code cannot be tested and a few parts of the system remain untested. So, DB interaction or network connection is mandatory for unit testing some parts of the system. To unit test these parts, you need to isolate the testing of unfriendly objects, or technically, the external dependencies need to be mocked out (or faked).

Mockito plays a key role in mocking external dependencies. Mockito can be used to mock out a database connection or any external I/O behavior so that the actual logic can be unit tested and your code can interact with the mocked external objects.

Mocking provides the following benefits:

  • Unit test reliability: You mock test unfriendly objects so that your test becomes reliable. They don't fail for any unavailable external object as you mock the external object.
  • Unit tests can be automated: Mockito makes unit test configuration simple as the tests can mock external dependencies, such as a web service call or database access.
  • Extremely fast test execution: Unit tests access mock objects, so delay in external service call or slow I/O operations can be isolated.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.15.43