Автор оригинала: Pankaj Kumar.
Аннотации Mockito @InjectMocks позволяют нам вводить издевательские зависимости в аннотированный объект издевательства над классом. Это полезно, когда у нас есть внешние зависимости в классе, над которым мы хотим издеваться. Мы можем указать фиктивные объекты, которые будут введены, используя аннотации @Mock или @Spy.
Mockito @InjectMocks
Mockito пытается внедрить издевательские зависимости, используя один из трех подходов, в указанном порядке.
- Инъекция на основе конструктора – когда для класса определен конструктор, Mockito пытается внедрить зависимости, используя самый большой конструктор.
- На основе методов настройки – когда не определены конструкторы, Mockito пытается внедрить зависимости с помощью методов настройки.
- На основе полей – если нет конструкторов или возможной инъекции на основе полей, то mockito пытается внедрить зависимости в само поле.
Если есть только один соответствующий макет объекта, то mockito введет его в объект. Если существует более одного поддельного объекта одного и того же класса, то имя поддельного объекта используется для введения зависимостей.
Пример макета @InjectMocks
Давайте создадим некоторые службы и классы с зависимостями, чтобы мы могли видеть, как Mockito внедряет зависимости в действие.
Классы обслуживания
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; } }
Классы служб приложений с зависимостями
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); } }
Пример Инъекции конструктора @InjectMocks
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")); } }
Вы заметили, что мой тестовый класс расширяется BaseTestCase
. Это делается для инициализации насмешек Mockito перед тестами, вот код класса.
package com.journaldev.mockito.injectmocks; import org.junit.jupiter.api.BeforeEach; import org.mockito.MockitoAnnotations; class BaseTestCase { @BeforeEach void init_mocks() { MockitoAnnotations.initMocks(this); } }
Если вы не будете вызывать MockitoAnnotations.initMocks(это);
тогда вы получите Исключение NullPointerException
.
Кроме того, я использую JUnit 5 для запуска тестовых случаев. Если вы не знакомы с ним, ознакомьтесь с руководством по JUnit 5 .
@InjectMocks Пример методов установки инъекций
@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")); }
@InjectMocks Пример Инъекции На Основе поля
@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")); }
Ссылка: API Doc