@Autowired Bean 在 Spring Boot 单元测试中为 NULL

alw*_*ava 17 java unit-testing spring-boot

我是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);

  }
}
Run Code Online (Sandbox Code Playgroud)

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

@Autowired
private OtherSampleClass sampleBean;
Run Code Online (Sandbox Code Playgroud)

在我的“OtherSampleClass”中,我注释了一个方法,如下所示:

@Bean(name = "sampleBean")
public void someMethod(){
....
}
Run Code Online (Sandbox Code Playgroud)

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

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

当我尝试像用户一样使用它时,该代码“正常”工作,因此我始终可以通过这种方式进行测试,但我认为自动化测试对程序的寿命有好处。

我已经使用Spring Boot 测试文档来帮助我解决这个问题。

Edd*_*ddy 8

以下配置对我有用。

文件: build.gradle

testCompile("junit:junit:4.12")
testCompile("org.springframework.boot:spring-boot-starter-test")
Run Code Online (Sandbox Code Playgroud)

文件: 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();
    }
}
Run Code Online (Sandbox Code Playgroud)


Gle*_*hil -4

最好尽可能将 Spring 排除在单元测试之外。无需自动装配您的 bean,只需将它们创建为常规对象即可

OtherSampleClass otherSampleClass = mock(OtherSampleClass.class);
SampleClass sampleClass = new SampleClass(otherSampleClass);
Run Code Online (Sandbox Code Playgroud)

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

替换这个

@Autowired
private OtherSampleClass sampleBean;
Run Code Online (Sandbox Code Playgroud)

有了这个

private OtherSampleClass sampleBean;

@Autowired
public SampleClass(OtherSampleClass sampleBean){
    this.sampleBean = sampleBean;
}
Run Code Online (Sandbox Code Playgroud)

看看这个答案的其他代码示例

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