在Spring中进行单元测试:将依赖注入到被测试的组件中。
在Spring中进行单元测试:将依赖注入到被测试的组件中。
我有一个非常简单的rest控制器:
@RestController public class MyController { @Autowired public Logger logger;
logger依赖通过以下配置注入:
@Configuration public class MyConfig { @Bean public Logger logger() { return LoggerFactory.getLogger(MyController.class); }
如果我运行包含控制器的Spring应用程序,一切正常。然而,当运行我的单元测试时,我无法实现这种依赖注入。在这种情况下,我有以下测试配置:
@Configuration @Profile("test") public class MyTestConfig { @Bean public Logger logger() { return LoggerFactory.getLogger(MyCOntroller.class); }
这是我单元测试代码的相关部分:
@RunWith(MockitoJUnitRunner.class) @ContextConfiguration(classes = MyTestConfig.class) @ActiveProfiles("test") public class MyContollerTest {
然而,logger对象在MyController中没有被"autowired"(注意我不想mock logger对象),这导致了空指针引用。
我漏掉了什么?
在Spring中进行单元测试时,我们不应该使用任何Spring配置。我们应该简单地实例化组件,并手动注入依赖(通常是虚拟的依赖)。
你使用了字段注入,这使得情况变得有点复杂。如果使用构造函数注入,你只需要做以下操作:
Logger logger = LoggerFactory.getLogger(MyController.class); MyController controller = new MyController(logger);
然而,即使使用字段注入,Mockito也可以帮助你注入虚拟依赖,这要归功于@InjectMocks
、@Mock
和@RunWith(MockitoJUnitRunner.class)
注解:
private Logger logger = LoggerFactory.getLogger(MyController.class); private MyController controller; public void prepare() { MockitoAnnotations.initMocks(this); }
话虽如此,如果我没记错的话,你没有使用@RunWith(SpringJUnit4ClassRunner.class)
,所以你的测试运行器对Spring一无所知,因此不会创建或使用任何Spring配置。
是的,我认为真正的问题在于SpringJUnit4ClassRunner
。这更像是一个集成测试而不是单元测试。
看来我在使用Spring进行单元测试时走错了路。在单元测试中使用字段注入并将Spring排除在外似乎是正确的做法。谢谢你的解释。
问题的出现原因:在进行单元测试时,通常不应该包含Spring配置。然而,如果仍然希望在Spring管理的bean上执行单元测试,可以使用SpringExtension的参数解析器。
解决方法:可以使用SpringExtension的参数解析器来在单元测试中注入依赖。在这个例子中,SpringExtension会自动使用,但是对于Controller测试,需要显式地添加。
具体的解决方法如下:
1. 在测试类上添加注解@ExtendWith(SpringExtension.class),以启用SpringExtension。
2. 在注解@ExtendWith(SpringExtension.class)中指定需要注入依赖的类,例如MyController.class、Myconfig.class和MyTestConfig.class。
3. 运行单元测试。
以下是示例代码:
import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.test.context.junit.jupiter.SpringExtension; @ExtendWith(SpringExtension.class) public class MyContollerTest { // 测试方法 }
通过以上方法,可以在进行单元测试时,将依赖注入到待测试的组件中。