单元测试中的 Spring Boot @Autowired 返回 NullPointerException

Posted

技术标签:

【中文标题】单元测试中的 Spring Boot @Autowired 返回 NullPointerException【英文标题】:Spring Boot @Autowired in unit test returns NullPointerException 【发布时间】:2020-11-20 22:57:39 【问题描述】:

我有一个用@service 注释的类(HttpHandler)。我正在为这个服务类编写单元测试用例。 我在我的测试类中使用了@Autowired 注解来获取服务的对象。但是,当我运行单元测试时,它返回 NullPOinterException。有人可以帮我吗?

下面是服务类的代码:

@Service
public class HttpHandler 

    private static final Logger logger = LoggerFactory.getLogger(HttpHandler.class);

    /**
     * Build the request and Perform Http Get request with headers
     * @param url
     * @param httpHeaders
     * @param responseClass
     * @param <T>
     * @param <R>
     * @return
     */
    public <T,R> ResponseEntity<T> sendPost(String url, HttpHeaders httpHeaders, R requestBody, Class<T> responseClass) 
        //create an instance of rest template
        RestTemplate restTemplate = new RestTemplate();
        HttpEntity<R> entity = new HttpEntity<R>(requestBody, httpHeaders);
        logger.info("POST request to " + url + " with body: " + JsonUtil.jsonizeExcludeNulls(requestBody));
        //make an HTTP POST request with headers
        ResponseEntity<T> response = restTemplate.exchange(url, HttpMethod.POST, entity, responseClass);
        logger.info("POST" + url + ": " + JsonUtil.jsonize(response));
        return response;
    

我正在为 POST 调用编写单元测试用例。下面是 POST 调用的单元测试 公共类 HttpHandlerTest

@Autowired
HttpHandler httpHandler;

@Test
public void testSuccessPostUser() throws Exception

    String baseUrl = "http://localhost:8080/users";
    List<String> messages = new ArrayList<>();
    messages.add("Hi");

    User user = new User();
    user.setId(1);
    user.setName("John");
    user.setAge(22);
    user.setMessages(messages);

    HttpHeaders httpHeaders = new HttpHeaders();
    httpHeaders.setContentType(MediaType.APPLICATION_JSON);
    httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));

    HttpEntity<User> httpEntity = new HttpEntity<>(user, httpHeaders);

    ResponseEntity<User> actual = httpHandler.sendPost(baseUrl, httpHeaders, user, User.class);

    //verify request succeed
    assertEquals(HttpStatus.CREATED, actual.getStatusCode());
    assertEquals(201, actual.getStatusCodeValue());
    assertTrue(actual.toString().contains("id"));

它给出以下错误:

java.lang.NullPointerException
    at com.xyz.provisioning.xyz.utils.HttpHandlerTest.testSuccessPostUser(HttpHandlerTest.java:41)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:686)
    at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
    at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
    at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)

【问题讨论】:

你有ApplicationTest主类吗? @silentsudo,是的,我有这是代码@SpringBootTest class XYZApplicationTests @Test void contextLoads() 但你的HttpHandlerTest上没有@SpringBootTest 抱歉错字!已对点击 sendPost 电话进行了更改。此外,在 HttpHandler 类上添加 @springBootTest 注释后,它不会给我 NullPointerException。 @SpringBootTest 加载完整的 Spring 上下文。如果你只是想测试你的服务,你可以使用Mockito 【参考方案1】:

对于 Junit 5(如 cmets 中所述),您只需在测试类顶部添加 @SpringBootTest

@SpringBootTest
class HttpHandlerTest
// ...

您不需要添加@ExtendWith(SpringExtension.class),因为由注解@SpringBootTest自动导入。

为了获得与 Junit 4 相同的结果:

@RunWith(SpringRunner.class)
@SpringBootTest
class HttpHandlerTest
// ...

【讨论】:

谢谢你们的时间和所有的帮助!!【参考方案2】:

如果您使用的是 JUnit5,请在类上方添加 @ExtendWith(SpringExtension.class),如果您使用的是 JUnit4,请添加 @RunWith(SpringRunner.class)

【讨论】:

锄头与@SpringBootTestMockito 相比,@ExtendWith(SpringExtension.class) 有什么不同吗? 使用 Junit5 不需要添加@ExtendWith(SpringExtension.class),因为由注解@SpringBootTest 自动导入。

以上是关于单元测试中的 Spring Boot @Autowired 返回 NullPointerException的主要内容,如果未能解决你的问题,请参考以下文章

单元测试中的 Spring Boot 数据源

单元测试中的 Spring Boot @Autowired 返回 NullPointerException

kotlin + Spring boot 中的单元测试休息控制器

java 裸机单元测试Spring Boot应用程序中的RestController方法。

[翻译]Spring Boot 中的集成测试

Spring Boot 单元测试,保姆级教程!