## Table of Contents
1. [Mockito](#mockito)
2. [Important Jargon](#important-jargon)
3. [How to get Mockito](#how-to-get-mockito)
4. [Annotations in Mockito library](#annotations-in-mockito-library)
5. [Mockito Exceptions](#mockito-exceptions)
6. [Mocking best practices](#mocking-best-practices)
7. [Drawbacks of Mocking](#drawback-of-mocking)
## Mockito
[Mockito](https://site.mockito.org/) is an Open Source Mocking framework. It is a Java library mostly used for unit testing of Java application. The Mockito library enables mock **creation**, **verification** and **stubbing**. It simplifies the process of testing by creating mock objects and avoiding external dependencies like connecting to database.
At present, Mockito frameworks consists of following set of libraries:
* **mockito-all** - It consist of mockito core library and other dependencies like *hamcrest*. This is <mark>outdated library with no future release</mark>. Developer should use mockito-core instead.
* **mockito-core** - It is a core mockito library, it contains both API and the implementation of library.
* **mockito-inline** - It provide advance feature of mocking constructors, final classes and static methods with the help of preconfigured inline <mark>Mock maker</mark>.
* **mockito-android** - Additional library provided for Mockito-Android support, use alongwith mockito-core.
* **mockito-testng** - Mockito utility classes for easy integration with **TestNG**
* **mockito-junit-jupiter** - Mockito extension for integration with Junit5+ (Junit Jupiter).
## Important Jargon
- **Mocking**
<mark>Creating objects that simulate the behaviour of real objects.</mark>
An object under test may have dependencies on other objects. In order to isolate the behaviour of the object that we want to test, we replace the dependencies (other objects) by mocking them to simulate the behaviour of the real objects.
Mocking is very useful during unit testing so that external dependencies are no longer a blocker to the code under testing. Most of the time these external dependencies may be under development. Hence, mocking helps to test the isolated code and speedup the deplopment process.
- **Stub**
Implementations of an interface suitable for a specific purpose or a given scenario. Generally stub have hard-coded logic. <mark>Stubbing define what values to return when we invoke a method of a mock object.</mark>
```
Mockito.when(mock.doSomething()).thenReturn(myStub()); //stubbing
//Stub method.
private obj myStub(){
MyClass obj = new MyClass();
obj.setName("MyClass");
return obj;
}
```
- **Fake**
Object actually have working implementation, but are not suitable for production usage.
- **Spy**
Spy is a stub that additionally record the information based on how they were called.
## How to get Mockito
Mockito libraries can be downloaded from [maven central repository](https://mvnrepository.com/artifact/org.mockito/mockito-core).
If you are using gradle then you can add `mockito-core` dependency in the gradle build script.
```
testCompile "org.mockito:mockito-core:4.9.0"
```
If you are using `Maven` as build tool then add `mockito-core` dependency in maven `pom.xml` file.
```
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-core -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>4.9.0</version>
<scope>test</scope>
</dependency>
```
If you are using Junit-5, then you need additional dependency for mockito - `mockito-junit-jupiter`.
```
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupitere</artifactId>
<version>4.9.0</version>
<scope>test</scope>
</dependency>
```
## Annotations in Mockito library
**@Mock**
It create and inject mock instance of a class.This is most widely used annotation. `@Mock` annotation is used with class level annotations `@RunWith` or `@ExtendWith`(for Junit5+). For **Spring framework** based projects you can also use `@RunWith(SpringRunner.class)` for Junit-4 or `@ExtendWith(SpringExtension.class)` for Junit 5+. The annotation `@Mock` can be used instead of using the `Mockito.mock()` method which allows us to create a mock object of a class.
For Junit 4 or prevous version:
```
@RunWith(MockitoJUnitRunner.class)
class DemoClassTest {
@Mock
MyDemoService myDemoService;
...
...
}
```
For Junit5+ :
```
@ExtendWith(MockitoExtension.class)
class DemoClassTest {
@Mock
MyDemoService myDemoService;
...
...
}
```
**@InjectMocks**
*Mockito* will search for a suitable public constructor to create an instance of the class where we have used `@InjectMocks` and pass all mocks to it. This is quite useful to test the behavior of a class completely.
**@Captor**
simplifies creation of `ArgumentCaptor` - useful when the arguments to capture is a nasty generic class and you want to avoid compiler warnings.
**@spy**
`@Spy` annotation to spy on an existing instance. It is used to spy on real objects.We can say it as partial Mock, which will track the interactions with the object like a mock. <mark>In case of spy real methods get executed unless we stub the methods. </mark>
## Mockito Exceptions
- **UnsupportedStubbingException**
This exception is one of the very common exceptions when use stubs incorrectly.
`Mockito` throw this exception when a given initialized mock is not called by the test methods during execution. Mockito use **strict stub** checking by default since Mockito 3.0 . We can either remove the unnecessary stubbing that is not being used by test methods or we can use *lenient* stub checking using `Mockito.lenient()` method or use `@MockitoSettings` annotation.
```
Mockito.lenient().when(Mockito.anyString()).thenReturn("Hello");
```
Change Stub checking settings using `@MockitoSettings`
```
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
class DemoClassTest {
@Mock
MyDemoService myDemoService;
...
...
}
```
## Mocking best practices
1. Do not mock types you don’t own
Only mock types that you own. Types that you don't own have dependencies on their own. These types might change their behaviour in future versions.
2. Don’t mock value objects
Values should not be mocked. Mocking aims to make the interaction and relationships between object visible.
3. Don’t mock everything
4. Avoid mocking concrete classes.
*Mock roles, not objects*
## Drawback of Mocking
1. Mocking need good understanding of dependencies.
2. Mocking can create tight coupling between mocks and code under testing.
3. Over use of mocking can leads to increase in code maintenance.
## Few Mocking Libraries and Framework
- PowerMock
- Mockito
- EasyMock
- jMock
>
Comments
Post a Comment