Java 使用@InjectMocks用模拟实现替换@Autowired字段
我想用我专门为测试而创建的类的模拟实现替换spring boot应用程序中的一个自动连接的服务类 我之所以选择创建这个模拟实现,是因为这个类的行为太复杂,无法使用mockito进行模拟,因为它本身需要多个其他模拟 我无法确定如何将这个模拟实现注入到服务中 下面是一个最简单的例子:Java 使用@InjectMocks用模拟实现替换@Autowired字段,java,unit-testing,junit,spring-boot,mockito,Java,Unit Testing,Junit,Spring Boot,Mockito,我想用我专门为测试而创建的类的模拟实现替换spring boot应用程序中的一个自动连接的服务类 我之所以选择创建这个模拟实现,是因为这个类的行为太复杂,无法使用mockito进行模拟,因为它本身需要多个其他模拟 我无法确定如何将这个模拟实现注入到服务中 下面是一个最简单的例子: @Service public class ServiceIWantToTestImpl implements ServiceIWantToTest{ @Autowired ComplicatedDe
@Service
public class ServiceIWantToTestImpl implements ServiceIWantToTest{
@Autowired
ComplicatedDependency complicatedDependency;
@Override
public void methodUsingDependency(){
String string = complicatedDependency.doSomething();
System.out.println(string);
}
}
public class MockComplicatedDependency implements ComplicatedDepencency{
public MockComplicatedDependency(...){
// Inject other mocked objects into this mock
}
public String doSomthing(){
// This would be a mocked version of this function for testing
return "test";
}
}
@RunWith(MockitoJUnitRunner.class)
public class TestingTheService(){
@InjectMock
private static ServiceIWantToTest serviceIWantToTest = new ServiceIWantToTestImpl();
@Mock
ComplicatedDependency mockComplicatedDependency;
@BeforeClass
public static void init(){
mockComplicatedDependency = new MockComplicatedDependency(...);
}
@Test
public void testAttempt(){
serviceIWantToTest.methodUsingDependency(); // This method calls complicatedDependency.doSomething() which does not run the mocked version in MockComplicatedDependency which I wanted to inject, and would always return null instead of the "test" string I put in this example.
}
}
您是否必须使用Mockito注释为测试中的类设置依赖项 如果这不是主要约束为什么不直接进行简单设置,并在
serviceiwanttoestimpl
类中为compleddependence
字段引入构造函数或setter,并直接将测试设置中的依赖项设置为您喜欢的任何复杂依赖项,例如:
@Service
public class ServiceIWantToTestImpl implements ServiceIWantToTest {
@Autowired
ComplicatedDependency complicatedDependency;
public ServiceIWantToTestImpl() {
}
public ServiceIWantToTestImpl(ComplicatedDependency complicatedDependency) {
this.complicatedDependency = complicatedDependency;
}
@Override
public void methodUsingDependency(){
String string = complicatedDependency.doSomething();
System.out.println(string);
}
}
public class TestingTheService {
private static ServiceIWantToTestImpl serviceIWantToTest;
@BeforeClass
public static void init(){
serviceIWantToTest = new ServiceIWantToTestImpl(new MockComplicatedDependency());
}
@Test
public void testAttempt() {
serviceIWantToTest.methodUsingDependency();
}
}
这是一种方式
要使它与Mockito一起工作,您可以使用@Spy而不是@Mock,如下所示:
@RunWith(MockitoJUnitRunner.class)
public class TestingTheService {
@InjectMocks
private static ServiceIWantToTestImpl serviceIWantToTest = new ServiceIWantToTestImpl();
@Spy
private static ComplicatedDependency complicatedDependency = new MockComplicatedDependency();
@BeforeClass
public static void init() {
}
@Test
public void testAttempt() {
serviceIWantToTest.methodUsingDependency();
}
}
虽然这有点像黑客。我强烈建议您阅读@Spy注释的JavaDoc,并确保它的预期用途是您测试所真正需要的。我按照您的建议尝试使用@Spy,效果很好。谢谢我真的不想仅仅为了测试而引入构造函数,我想让spring处理应用程序中的依赖注入。实际上,构造函数级注入是推荐的方法,字段级注入通常是不推荐的,Spring已经推荐构造函数注入十年了:。没有人应该再使用现场注射了。啊哈,非常有趣!谢谢你提供的信息,我是自学成才的程序员,所以我的知识有很多漏洞。