java - Spring Rest Controller 测试中的 NullPointer 异常 - Java

标签 java spring unit-testing spring-mvc nullpointerexception

我在 Spring-Boot 1.4 中有以下 Rest Controller 和单元测试:

HealthChecker Controller :

@RestController
public class HealthCheckerController {

   @Autowired
   private InstanceRepository instanceRepository;

   @RequestMapping(value = "/healthchecker", method = RequestMethod.GET)
   @ResponseBody
   public List<Instance> findAll() {
       return this.instanceRepository.findAll();
   }

健康检查 Controller 测试:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
@WebAppConfiguration
public class HealthCheckerControllerTest {

    private MockMvc mvc;

    @Autowired
    private InstanceRepository instanceRepository;

    @Before
    public void setUp() throws Exception {
        mvc = MockMvcBuilders.standaloneSetup(new HealthCheckerController()).build();

        this.instanceRepository.deleteAll();
        Instance first = new Instance("10.20.30.40", "ami-xxxxxxxx");
        Instance second = new Instance("10.20.30.41", "ami-xxxxxxxx");
        this.instanceRepository.save(first);
        this.instanceRepository.save(second);

        for (Instance instance : this.instanceRepository.findAll()) {
            System.out.println(instance);
        }
    }

    @Test
    public void testHealthChecker() throws Exception {
        mvc.perform(get("/healthchecker")).andExpect(status().isOk())
                .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)).andExpect(jsonPath("$", hasSize(2)))
                .andExpect(jsonPath("$[0].ipaddress", is("10.20.30.40")))
                .andExpect(jsonPath("$[0].ami", is("ami-xxxxxxxx")))
                .andExpect(jsonPath("$[1].ipaddress", is("10.20.30.41")))
                .andExpect(jsonPath("$[1].ami", is("ami-xxxxxxxx")));
    }
}

但是,当我执行单元测试时,出现以下错误:

Tests run: 21, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 19.83 sec <<< FAILURE! - in TestSuite
testHealthChecker on testHealthChecker(cloudos.HealthCheckerControllerTest)(cloudos.HealthCheckerControllerTest)  Time elapsed: 0.193 sec  <<< FAILURE!
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NullPointerException
    at cloudos.HealthCheckerController.findAll(HealthCheckerController.java:39)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:114)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:65)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:167)
    at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:134)
    at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:155)
    at cloudos.HealthCheckerControllerTest.testHealthChecker(HealthCheckerControllerTest.java:48)

从 UI 访问它工作正常:

[{"ipaddress":"10.20.30.40","ami":"ami-xxxxxxxx"},{"ipaddress":"10.20.30.41","ami":"ami-xxxxxxxx"}]

我知道问题是 private InstanceRepository instanceRepository 没有在 unit test 中初始化,所以当它在 HealthCheckerController 中被访问时null,但这不是 @Autowired 的目的? 我该如何解决这个问题?

最佳答案

当您使用 MockMvcBuilders.standaloneSetup 时,您需要手动设置您的 Controller 对象(它更适合单元测试)

如果你想使用完整的 Spring 上下文(所有 @Autowired 字段可用)你将需要使用 MockMvcBuilders.webAppContextSetup

这应该有效:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
@WebAppConfiguration
public class HealthCheckerControllerTest {

    private MockMvc mvc;

    @Autowired
    private WebApplicationContext webApplicationContext;

    @Autowired
    private InstanceRepository instanceRepository;

    @Before
    public void setUp() throws Exception {

        mvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();

        this.instanceRepository.deleteAll();
        Instance first = new Instance("10.20.30.40", "ami-xxxxxxxx");
        Instance second = new Instance("10.20.30.41", "ami-xxxxxxxx");
        this.instanceRepository.save(first);
        this.instanceRepository.save(second);

        for (Instance instance : this.instanceRepository.findAll()) {
            System.out.println(instance);
        }
    }

    @Test
    public void testHealthChecker() throws Exception {
        mvc.perform(get("/healthchecker")).andExpect(status().isOk())
                .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)).andExpect(jsonPath("$", hasSize(2)))
                .andExpect(jsonPath("$[0].ipaddress", is("10.20.30.40")))
                .andExpect(jsonPath("$[0].ami", is("ami-xxxxxxxx")))
                .andExpect(jsonPath("$[1].ipaddress", is("10.20.30.41")))
                .andExpect(jsonPath("$[1].ami", is("ami-xxxxxxxx")));
    }
}

您最终可以尝试将构造函数添加到您的 Controller 并手动将现有存储库注入(inject)新创建的 Controller :

@RestController
public class HealthCheckerController {

    @Autowired
    private InstanceRepository instanceRepository;

    public HealthCheckerController(InstanceRepository instanceRepository) {
        this.instanceRepository = instanceRepository;
    }

    @RequestMapping(value = "/healthchecker", method = RequestMethod.GET)
    @ResponseBody
    public List<Instance> findAll() {
        return this.instanceRepository.findAll();
    }
}

您的 mvc 配置应如下所示:

mvc = MockMvcBuilders.standaloneSetup(new HealthCheckerController(instanceRepository)).build();

关于java - Spring Rest Controller 测试中的 NullPointer 异常 - Java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39056582/

相关文章:

java - Eclipse RCP 和 SWT 小部件和 NLS

java - 非法 block 大小异常 : Input length must be multiple of 8 when decrypting with padded cipher

java - Selenium WebDriver出现异常怎么办?

java - 如何配置 GAE/java servlet 的 url 路径

javascript - 使用 Jest 对 Electron-React 应用程序进行单元测试,TypeError : Cannot match against 'undefined' or 'null'

java - 将属性加载到 InputStream 中

java - 多模块项目中的spring配置

java - 在 JBOSS EAP 6.2.0 上部署 war 时如何抑制类路径条目警告?

java - 支持所有浏览器的网络应用程序?

java - 为软件 QA 类(class)的介绍编写一个简单的 JUnit 测试?