Mockito by default can mock interface, abstract class, and normal class, but it cannot mock the final class and final method. if tried then it will give an error.
Mockito cannot mock/spy because :
- final class
Although Mockito does support mocking of final classes and methods with the help of the mock maker extension It is disabled by default. the mock maker can be activated explicitly by the Mockito extension mechanism.
By default, Mockito creates a new class to represent a mock, but The mock maker extension uses both Java instrumentation API and sub-classing. hence it becomes possible to mock final types and methods. Mockito Privodes 2 ways to enable mock maker extension.
- MockMaker config file
- Mockito-inline artifact
MockMaker config file
In older versions of Mockito mock maker extension could be activated by creating a config file org.mockito.plugins.MockMaker
in resources/mockito-extensions
directory.
mock-maker-inline
package com.example.mokito3.sujan;
public class AppleRepo {
final String saveApple(String apple) {
String appleString = "i have " + apple + " apple";
return appleString;
}
}
package com.example.mokito3.sujan;
public final class AppleService {
String saveApple(String apple) {
String appleString = "i love " + apple + " apple";
return appleString;
}
}
package com.example.mokito3.sujan;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
public class AppleServiceTest {
@Mock
private AppleService appleService;
@Mock
private AppleRepo appleRepo;
@Test
void saveAppleFinalClassMockTest() {
when(appleService.saveApple("Macintosh")).thenReturn("i eat apple");
String apple = appleService.saveApple("Macintosh");
verify(appleService).saveApple("Macintosh");
assertEquals("i eat apple", apple);
}
@Test
void saveAppleFinalMethodMockTest() {
when(appleRepo.saveApple("Macintosh")).thenReturn("i eat apple");
String apple = appleRepo.saveApple("Macintosh");
verify(appleRepo).saveApple("Macintosh");
assertEquals("i eat apple", apple);
}
}
plugins {
id 'java'
}
group 'org.example'
version '1.0-SNAPSHOT'
repositories { jcenter() }
dependencies {
testImplementation('org.junit.jupiter:junit-jupiter:5.6.2')
testCompile 'org.mockito:mockito-junit-jupiter:3.4.4'
}
test {
useJUnitPlatform()
}
mockito-inline artifact
Creating a separate config file just to enable an extension is boilerplate code. To make it more convenient latest versions of Mockito provide mockito-inline
artifact in which the mock maker is preconfigured.
mockito-inline artifact
artifact will be discontinued once final classes and methods mocking get integrated into the default mock maker.
package com.example.mokito3.sujan;
public final class AppleService {
String saveApple(String apple) {
String appleString = "i love " + apple + " apple";
return appleString;
}
}
package com.example.mokito3.sujan;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
public class AppleServiceTest {
@Mock
private AppleService appleService;
@Mock
private AppleRepo appleRepo;
@Test
void saveAppleFinalClassMockTest() {
when(appleService.saveApple("Macintosh")).thenReturn("i eat apple");
String apple = appleService.saveApple("Macintosh");
verify(appleService).saveApple("Macintosh");
assertEquals("i eat apple", apple);
}
@Test
void saveAppleFinalMethodMockTest() {
when(appleRepo.saveApple("Macintosh")).thenReturn("i eat apple");
String apple = appleRepo.saveApple("Macintosh");
verify(appleRepo).saveApple("Macintosh");
assertEquals("i eat apple", apple);
}
}
plugins {
id 'java'
}
group 'org.example'
version '1.0-SNAPSHOT'
repositories { jcenter() }
dependencies {
testImplementation('org.junit.jupiter:junit-jupiter:5.6.2')
testCompile 'org.mockito:mockito-junit-jupiter:3.4.4'
testCompile 'org.mockito:mockito-inline:3.4.4'
}
test {
useJUnitPlatform()
}