【问题标题】:@Autowired Bean is NULL in Spring Boot Unit Test@Autowired Bean 在 Spring Boot 单元测试中为 NULL
【发布时间】:2018-06-15 06:11:14
【问题描述】:

我是 JUnit 和自动化测试的新手,我真的很想自动化我的测试。这是一个 Spring Boot 应用程序。我使用了基于 Java 的注释样式而不是基于 XML 的配置。

我有一个测试类,我想在其中测试一个根据用户输入检索响应的方法。

测试类:

@RunWith(SpringRunner.class)
@SpringBootTest
public class SampleTest(){

  @Autowired
  private SampleClass sampleClass;

  @Test
  public void testInput(){

  String sampleInput = "hi";

  String actualResponse = sampleClass.retrieveResponse(sampleInput);

  assertEquals("You typed hi", actualResponse);

  }
}

在我的“SampleClass”中,我自动装配了一个这样的 bean。

@Autowired
private OtherSampleClass sampleBean;

在我的“OtherSampleClass”中,我注释了这样一个方法:

@Bean(name = "sampleBean")
public void someMethod(){
....
}

我遇到的问题是,当我尝试在没有 @RunWith 和 @SpringBootTest 注释的情况下运行测试时,当我尝试运行测试时,注释为 @Autowired 的变量为空。当我尝试使用这些注释 RunWith 和 SpringBootTest 运行测试时,我得到一个

BeanCreationException 导致的 IllegalStateException:创建时出错 名称为“sampleBean”的 bean 并且无法加载应用程序上下文 由 BeanInstantiationException 引起。

当我尝试像用户一样使用它时,代码“正常”工作,所以我总是可以用这种方式进行测试,但我认为自动化测试有利于程序的寿命。

我已经使用Spring Boot Testing Docs 来帮助我。

【问题讨论】:

  • 请添加您的SampleClass。
  • 带有@Bean注解的方法应该返回一个对象,即新的Spring Bean。
  • Spring 注入你的自动装配的 bean。如果您不使用 spring runner 运行,则没有任何东西可以注入,因此成员保持默认值(null)。请在使用 spring 运行时显示更多异常。根本原因可能是类路径或未找到属性失败。

标签: java unit-testing spring-boot


【解决方案1】:

以下配置对我有用。

文件:build.gradle

testCompile("junit:junit:4.12")
testCompile("org.springframework.boot:spring-boot-starter-test")

文件:MYServiceTest.java

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;

@SpringBootTest(classes = Application.class,
    webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles("test")
@RunWith(SpringRunner.class)
public class MYServiceTest {

    @Autowired
    private MYService myService;

    @Test
    public void test_method() {
        myService.run();
    }
}

【讨论】:

    【解决方案2】:

    最好尽可能将 Spring 排除您的 unit 测试。而不是自动装配您的 bean,只需将它们创建为常规对象

    OtherSampleClass otherSampleClass = mock(OtherSampleClass.class);
    SampleClass sampleClass = new SampleClass(otherSampleClass);
    

    但是为此,您需要使用构造函数注入而不是字段注入来提高可测试性。

    替换这个

    @Autowired
    private OtherSampleClass sampleBean;
    

    有了这个

    private OtherSampleClass sampleBean;
    
    @Autowired
    public SampleClass(OtherSampleClass sampleBean){
        this.sampleBean = sampleBean;
    }
    

    查看this 答案以获取其他代码示例

    【讨论】:

    • 使用模拟对象进行测试并不理想。有了 Spring Boot 测试和现代测试框架,可以放心,Spring Web 客户端..不需要模拟事物,最重要的是关于为什么自动装配不起作用,而不是关于如何测试类。
    • @Yogi 如果您正在测试控制器、进行集成测试和 E2E 测试,这是正确的,但对于单元测试,您应该尽可能避免使用 spring,因为它会产生很多开销
    【解决方案3】:

    无需注入 (@Autowired private SampleClass sampleClass;) 您正在测试的实际类,并删除 SpringBootTest 注释,
    用于集成测试用例的 SpringBootTest 注释。
    找到下面的代码会对你有所帮助。

    @RunWith(SpringRunner.class)
    public class SampleTest(){
    
      private SampleClass sampleClass;
    

    【讨论】:

    • 这应该如何回答一个关于如何做@Autowired的问题?
    猜你喜欢
    • 2018-07-19
    • 2020-11-20
    • 2020-11-04
    • 2014-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多