【问题标题】:Must use mockbean instead of autowired必须使用 mockbean 而不是 autowired
【发布时间】:2018-07-08 06:53:54
【问题描述】:

我用的是spring boot 2

我创建了一个基本测试

@RunWith(SpringJUnit4ClassRunner.class)
public class VehicleServiceImplTest {

    private VehiculeServiceImpl service;

    @Autowired
    private VehicleRepository repository;

    @Before
    public void prepare() {
        service = new VehiculeServiceImpl(repository);
    }

    @Test
    public void test(){

    }

}

我明白了

org.springframework.beans.factory.UnsatisfiedDependencyException: 创建具有名称的 bean 时出错 'com.namur.service.VehicleServiceImplTest':不满足的依赖关系 通过字段“存储库”表示;嵌套异常是 org.springframework.beans.factory.NoSuchBeanDefinitionException: 否 'com.namur.repository.VehicleRepository' 类型的合格 bean 可用:预计至少有 1 个符合 autowire 条件的 bean 候选人。依赖注解: {@org.springframework.beans.factory.annotation.Autowired(required=true)} 在 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:586)

如果我用 MockBean 替换 Autowired,它可以工作,但我不知道为什么

【问题讨论】:

    标签: spring-boot junit


    【解决方案1】:

    这是因为您没有为测试提供任何关于 spring 上下文是什么的指示,因此根本没有可用于自动装配的 bean。

    通过提供@MockBean,您实际上是在提供一个带有单个现有bean 的测试上下文,该bean 是VehicleRepository 类的模拟。

    您可以使用 @SpringBootTest 注释,它将加载一个弹簧上下文供您在测试中使用。然后你应该能够@Autowire 实际的存储库:

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringBootTest
    public class VehicleServiceImplTest {
    

    【讨论】:

    • 根据这个问题的标题,这应该是公认的答案。简明扼要。
    【解决方案2】:

    如果我用 MockBean 替换 Autowired,它可以工作,但我不知道为什么

    之所以有效,是因为 @MockBean 替换或添加一个 bean 进入 Spring 上下文。
    在您的情况下,它在 Spring 上下文中添加了一个 repository 模拟。
    所以这不能抛出任何UnsatisfiedDependencyException

    但这并不是您最初使用 @Autowired 所需要的,它旨在上下文注入 bean。

    @Autowired@MockBean 确实是两个截然不同的东西,你永远无法替代相同的需求。


    附带说明一下,您可能应该重新考虑构建测试的方式。

    实际上你使用的是SpringJUnit4ClassRunner runner。
    这意味着您想使用 Spring 容器进行测试。
    这是一种有效的方法。但是在这种情况下,为什么要在 Spring 容器之外创建 VehiculeServiceImpl 呢?

     service = new VehiculeServiceImpl(repository);
    

    您应该注入服务。

    请注意,在容器外创建被测类的新实例也是一种非常有效的方法。
    我们在编写简单的单元测试时这样做。如果您想这样做,请不要使用 Spring Boot 运行器,顺便说一下,这会使测试变慢。

    【讨论】:

    • 我的服务在参数中获取一个存储库
    • 没关系。您可以通过这种方式将其注入到您的测试中:@Autowired private VehicleService service;。您只需确保在测试类声明中正确使用了应用程序上下文。用@SpringBootTest注释类可以做到。
    猜你喜欢
    • 1970-01-01
    • 2011-02-25
    • 2023-03-29
    • 2019-07-01
    • 2018-09-13
    • 1970-01-01
    • 2014-10-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多