By Pankaj Kumar
Mockito @InjectMocks annotations allow us to inject mocked dependencies in the annotated class mocked object. This is useful when we have external dependencies in the class we want to mock. We can specify the mock objects to be injected using @Mock or @Spy annotations.
Mockito tries to inject mocked dependencies using one of the three approaches, in the specified order.
If there is only one matching mock object, then mockito will inject that into the object. If there is more than one mocked object of the same class, then mock object name is used to inject the dependencies.
Let’s create some services and classes with dependencies so that we can see Mockito dependency injection of mocks in action. Service Classes
package com.journaldev.injectmocksservices;
public interface Service {
public boolean send(String msg);
}
package com.journaldev.injectmocksservices;
public class EmailService implements Service {
@Override
public boolean send(String msg) {
System.out.println("Sending email");
return true;
}
}
package com.journaldev.injectmocksservices;
public class SMSService implements Service {
@Override
public boolean send(String msg) {
System.out.println("Sending SMS");
return true;
}
}
App Service Classes with Dependencies
package com.journaldev.injectmocksservices;
//For Constructor Based @InjectMocks injection
public class AppServices {
private EmailService emailService;
private SMSService smsService;
public AppServices(EmailService emailService, SMSService smsService) {
this.emailService = emailService;
this.smsService = smsService;
}
public boolean sendSMS(String msg) {
return smsService.send(msg);
}
public boolean sendEmail(String msg) {
return emailService.send(msg);
}
}
package com.journaldev.injectmocksservices;
//For Property Setter Based @InjectMocks injection
public class AppServices1 {
private EmailService emailService;
private SMSService smsService;
public void setEmailService(EmailService emailService) {
this.emailService = emailService;
}
public void setSmsService(SMSService smsService) {
this.smsService = smsService;
}
public boolean sendSMS(String msg) {
return smsService.send(msg);
}
public boolean sendEmail(String msg) {
return emailService.send(msg);
}
}
package com.journaldev.injectmocksservices;
//For Field Based @InjectMocks injection
public class AppServices2 {
private EmailService emailService;
private SMSService smsService;
public boolean sendSMS(String msg) {
return smsService.send(msg);
}
public boolean sendEmail(String msg) {
return emailService.send(msg);
}
}
package com.journaldev.mockito.injectmocks;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import com.journaldev.injectmocksservices.AppServices;
import com.journaldev.injectmocksservices.AppServices1;
import com.journaldev.injectmocksservices.AppServices2;
import com.journaldev.injectmocksservices.EmailService;
import com.journaldev.injectmocksservices.SMSService;
class MockitoInjectMocksExamples extends BaseTestCase {
@Mock EmailService emailService;
@Mock SMSService smsService;
@InjectMocks AppServices appServicesConstructorInjectionMock;
@InjectMocks AppServices1 appServicesSetterInjectionMock;
@InjectMocks AppServices2 appServicesFieldInjectionMock;
@Test
void test_constructor_injection_mock() {
when(appServicesConstructorInjectionMock.sendEmail("Email")).thenReturn(true);
when(appServicesConstructorInjectionMock.sendSMS(anyString())).thenReturn(true);
assertTrue(appServicesConstructorInjectionMock.sendEmail("Email"));
assertFalse(appServicesConstructorInjectionMock.sendEmail("Unstubbed Email"));
assertTrue(appServicesConstructorInjectionMock.sendSMS("SMS"));
}
}
Did you noticed that my test class is extending BaseTestCase
. This is to initialize Mockito mocks before the tests, here is the code of the class.
package com.journaldev.mockito.injectmocks;
import org.junit.jupiter.api.BeforeEach;
import org.mockito.MockitoAnnotations;
class BaseTestCase {
@BeforeEach
void init_mocks() {
MockitoAnnotations.initMocks(this);
}
}
If you won’t call MockitoAnnotations.initMocks(this);
then you will get NullPointerException
. Also, I am using JUnit 5 to run the test cases. If you are not familiar with it, have a look at JUnit 5 Tutorial.
@Test
void test_setter_injection_mock() {
when(appServicesSetterInjectionMock.sendEmail("New Email")).thenReturn(true);
when(appServicesSetterInjectionMock.sendSMS(anyString())).thenReturn(true);
assertTrue(appServicesSetterInjectionMock.sendEmail("New Email"));
assertFalse(appServicesSetterInjectionMock.sendEmail("Unstubbed Email"));
assertTrue(appServicesSetterInjectionMock.sendSMS("SMS"));
}
@Test
void test_field_injection_mock() {
when(appServicesFieldInjectionMock.sendEmail(anyString())).thenReturn(true);
when(appServicesFieldInjectionMock.sendSMS(anyString())).thenReturn(true);
assertTrue(appServicesFieldInjectionMock.sendEmail("Email"));
assertTrue(appServicesFieldInjectionMock.sendEmail("New Email"));
assertTrue(appServicesFieldInjectionMock.sendSMS("SMS"));
}
You can check out complete code and more Mockito examples from our GitHub Repository.
Reference: API Doc
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
Java and Python Developer for 20+ years, Open Source Enthusiast, Founder of https://www.askpython.com/, https://www.linuxfordevices.com/, and JournalDev.com (acquired by DigitalOcean). Passionate about writing technical articles and sharing knowledge with others. Love Java, Python, Unix and related technologies. Follow my X @PankajWebDev
Mockito now has a JUnit5 extension to avoid having to call explicitly to initMocks(). Just adding @ExtendWith(MockitoExtension.class) At the top of the class, equivalent to the JUnit4’s @RunWith(… Dependency is: org.mockito mockito-junit-jupiter 3.5.11 test Please update the post, thanks.
- brujua
Why are you writing when(appServicesFieldInjectionMock.sendEmail(anyString())).thenReturn(true); ??? It should be when(emailService.send(anyString()) … Otherwise what is the purpose of @Mock annotated objects here.
- stupid
The sample looks confuse… mocking the class you try to test… what are you testing then? your class? no… Mockito maybe?
- Domingo Berrón
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.
Full documentation for every DigitalOcean product.
The Wave has everything you need to know about building a business, from raising funding to marketing your product.
Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.
New accounts only. By submitting your email you agree to our Privacy Policy
Scale up as you grow — whether you're running one virtual machine or ten thousand.
Sign up and get $200 in credit for your first 60 days with DigitalOcean.*
*This promotional offer applies to new accounts only.