Mockito @InjectMocks –模拟依赖注入
时间:2020-02-23 14:40:44 来源:igfitidea点击:
Mockito @InjectMocks批注允许我们将模拟的依赖项注入带注释的类模拟对象中。
当我们要模拟的类中具有外部依赖项时,这很有用。
我们可以使用@Mock或者@Spy批注指定要注入的模拟对象。
Mockito @InjectMocks
Mockito尝试使用三种方法之一以指定的顺序注入模拟的依赖项。
基于构造函数的注入–当为类定义了构造函数时,Mockito尝试使用最大的构造函数注入依赖项。
基于Setter方法-当未定义构造函数时,Mockito尝试使用setter方法注入依赖项。
基于字段的–如果没有构造函数或者基于字段的注入可能,那么Mockito尝试将依赖项注入字段本身。
如果只有一个匹配的模拟对象,则模拟将把它注入到对象中。
如果同一类的模拟对象不止一个,则使用模拟对象名称来注入依赖项。
模拟@InjectMocks示例
让我们创建一些具有依赖项的服务和类,以便我们可以看到Mockito依赖项注入了模拟。
服务等级
package com.theitroad.comjectmocksservices;
public interface Service {
public boolean send(String msg);
}
package com.theitroad.comjectmocksservices;
public class EmailService implements Service {
@Override
public boolean send(String msg) {
System.out.println("Sending email");
return true;
}
}
package com.theitroad.comjectmocksservices;
public class SMSService implements Service {
@Override
public boolean send(String msg) {
System.out.println("Sending SMS");
return true;
}
}
具有依赖关系的App Service类
package com.theitroad.comjectmocksservices;
//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.theitroad.comjectmocksservices;
//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.theitroad.comjectmocksservices;
//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.theitroad.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.theitroad.comjectmocksservices.AppServices;
import com.theitroad.comjectmocksservices.AppServices1;
import com.theitroad.comjectmocksservices.AppServices2;
import com.theitroad.comjectmocksservices.EmailService;
import com.theitroad.comjectmocksservices.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.theitroad.mockito.injectmocks;
import org.junit.jupiter.api.BeforeEach;
import org.mockito.MockitoAnnotations;
class BaseTestCase {
@BeforeEach
void init_mocks() {
MockitoAnnotations.initMocks(this);
}
}
如果您不调用MockitoAnnotations.initMocks(this);,则将获得NullPointerException。
另外,我正在使用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"));
}

