Las anotaciones @InjectMocks de Mockito nos permiten inyectar dependencias simuladas en el objeto simulado de la clase anotada. Esto es útil cuando tenemos dependencias externas en la clase que queremos simular. Podemos especificar los objetos simulados que se inyectarán usando las anotaciones @Mock o @Spy .
Mockito @InjectMocks
Mockito intenta inyectar dependencias simuladas utilizando uno de los tres enfoques, en el orden especificado.
- Inyección basada en constructor: cuando hay un constructor definido para la clase, Mockito intenta inyectar dependencias utilizando el constructor más grande.
- Basado en métodos setter: cuando no hay constructores definidos, Mockito intenta inyectar dependencias utilizando métodos setter.
- Basado en campo: si no hay constructores o inyecciones basadas en campos posibles, entonces Mockito intenta inyectar dependencias en el campo mismo.
Si solo hay un objeto simulado coincidente, Mockito lo inyectará en el objeto. Si hay más de un objeto simulado de la misma clase, se utiliza el nombre del objeto simulado para inyectar las dependencias.
Ejemplo de Mock @InjectMocks
Creemos algunos servicios y clases con dependencias para que podamos ver la inyección de dependencias de Mockito en acción. Clases de servicio
package com.journaldev.injectmocksservices;public interface Service {public boolean send(String msg);}
package com.journaldev.injectmocksservices;public class EmailService implements Service {@Overridepublic boolean send(String msg) {System.out.println("Sending email");return true;}}
package com.journaldev.injectmocksservices;public class SMSService implements Service {@Overridepublic boolean send(String msg) {System.out.println("Sending SMS");return true;}}
Clases de App Service con dependencias
package com.journaldev.injectmocksservices;//For Constructor Based @InjectMocks injectionpublic 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 injectionpublic 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 injectionpublic 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);}}
Ejemplo de inyección de constructor @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;@Testvoid 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"));}}
¿Has notado que mi clase de prueba se extiende a BaseTestCase? Esto es para inicializar los mocks de Mockito antes de las pruebas, aquí está el código de la clase.
package com.journaldev.mockito.injectmocks;import org.junit.jupiter.api.BeforeEach;import org.mockito.MockitoAnnotations;class BaseTestCase {@BeforeEachvoid init_mocks() {MockitoAnnotations.initMocks(this);}}
Si no llama MockitoAnnotations.initMocks(this);, obtendrá NullPointerException. Además, estoy usando JUnit 5 para ejecutar los casos de prueba. Si no está familiarizado con él, eche un vistazo al Tutorial de JUnit 5 .
Ejemplo de inyección de métodos de establecimiento de @InjectMocks
@Testvoid 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"));}
Ejemplo de inyección basada en campos @InjectMocks
@Testvoid 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"));}
Puede consultar el código completo y más ejemplos de Mockito en nuestro repositorio de GitHub .
Referencia: Documentación de la API