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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/48113464/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 09:58:56  来源:igfitidea点击:

@Autowired Bean is NULL in Spring Boot Unit Test

javaunit-testingspring-boot

提问by alwaysStuckJava

I am new to JUnitand automated testing and really want to get into automating my tests. This is a Spring Boot application. I have used Java Based Annotation style instead of XML based configuration.

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

I have a test class in which I'd like to test a method which retrieves a response based on a users' input.

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

Testing class:

测试类:

@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);

  }
}

Inside my "SampleClass" I have autowired a bean like this.

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

@Autowired
private OtherSampleClass sampleBean;

Inside my "OtherSampleClass" I have annotated a method like so:

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

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

The issue I'm having is when I try to run the test without the @RunWithand @SpringBootTestannotations when I try to run the test my variables annotated @Autowiredare null. And when I try to run the test with those annotations RunWith & SpringBootTest then I get an

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

IllegalStateException caused by BeanCreationException: Error creating bean with name "sampleBean" AND failure to load application context caused by BeanInstantiationException.

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

The code works 'properly' when I try to use it as a user would so I can always test this way but I think automated tests would be good for the longevity of the program.

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

I have used the Spring Boot Testing Docsto assist me in this.

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

回答by Eddy

The following config works for me.

以下配置对我有用。

File: build.gradle

文件: build.gradle

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

File: MYServiceTest.java

文件: 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();
    }
}

回答by Glenn Van Schil

It's best to keep Spring outof your unittests as much as possible. Instead of Autowiring your bean just create them as a regular object

最好尽可能将 Spring排除单元测试之外。而不是自动装配你的 bean 只是将它们创建为一个常规对象

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

But for this you need to use the Constructor injection instead of Field Injection which improves testability.

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

Replace this

替换这个

@Autowired
private OtherSampleClass sampleBean;

With this

有了这个

private OtherSampleClass sampleBean;

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

Take a look at thisanswer for an other code example

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

回答by AdamIJK

No need to inject (@Autowired private SampleClass sampleClass;) your actual class which you are testing, and remove SpringBootTest annotation,
SpringBootTest annotation used for integration test cases.
find the following code will help you.

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

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

  private SampleClass sampleClass;