【问题标题】:NullPointerException while trying to test a Spring MVC controller method with JUnit, Mockito尝试使用 JUnit、Mockito 测试 Spring MVC 控制器方法时出现 NullPointerException
【发布时间】:2020-11-27 14:49:35
【问题描述】:

我正在尝试对 Spring MVC 控制器方法进行单元测试,但我的单元测试一直失败。

我有一个 Spring MVC 控制器方法:

// MyController.java
@RequestMapping(value = "/end-point", method = RequestMethod.GET)
public ModelAndView getData(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
    ModelAndView mv = new ModelAndView();
    DataManager dataManager = DataManager.getInstance();
    DataUser currentUser = (DataUser) request.getSession().getAttribute("currentUser");
    List<DataItem> dataList = dataManager.getDataForUser(currentUser.getId());
    mv.addObject("dataList", dataList);
    mv.setViewName("home-page");
    return mv;
}

我正在尝试使用 JUnit 测试此控制器方法。我几乎没有单元测试经验,正在努力学习。似乎这几乎是不可能的,或者没有模拟库就没有意义,而且我正在处理的项目已经将 Mockito 作为依赖项,所以我正在尝试使用它。我的测试类如下:

//MyControllerTest.java
public class MyControllerTest {
    @InjectMocks
    private MyController myController;

    @Mock
    HttpServletRequest request;

    @Mock
    HttpServletResponse response;

    @Mock
    ModelAndView mockModelAndView;

    @Mock
    DataManager mockDataManager;

    @Mock
    DataUser mockDataUser;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void getDataTest() throws Exception {
        //I guess I have to somehow mock mockDataUser here even more than @Mock???
        Mockito.when(request.getSession().getAttribute("currentUser")).thenReturn(mockVendorUser); // <-- this is where the null pointer exception is coming from
        Mockito.when(myController.getData(request, response)).thenReturn(mockModelAndView); 
        ModelAndView testing = profileControllerWH.getMySkus(request, response);
        assertEquals(1, 1);
    }
}

当我运行我的测试时,它失败了,我在控制台中得到了一个java.lang.NullPointerException 异常,用空指针异常注释指定了上面的行。

我尝试查找如何使用 Mockito 模拟类,并且我一直看到 @Mock 注释,我已经拥有 @Mock DataUser (以及我在控制器方法中使用的其他类,我猜我需要模拟)。

如何让它工作?似乎我必须用假数据创建一个全新的DataUser 对象,但这似乎违背了模拟库的目的。如果我必须用假数据创建自己的对象,那么使用 Mockito 有什么意义?或者,我可能因为缺乏经验而误解了这一点。

【问题讨论】:

  • 对于您的 Spring MVC 控制器端点,使用MockMvc 编写测试可能更有意义,否则您最终会模拟所有内容并复制您的实现。以下guide about MockMvc 可能是一个好的开始。

标签: java spring-mvc junit mockito


【解决方案1】:

请记住,默认情况下,未存根的方法在调用时返回返回类型的默认值(数字为 0,对象为 null)。

你还没有存根 request.getSession() 所以它返回 null。

你需要:

  • 为会话提供模拟
  • 存根 request.getSession() 以返回此模拟
  • 存根session.getAttribute("currentUser")

最重要的是:

虽然在您的测试中调用控制器方法当然具有测试方法主体的价值,但如果您将测试重新实现为@WebMvcTest,您将测试更多功能(如请求和响应序列化)

【讨论】:

    猜你喜欢
    • 2020-09-11
    • 1970-01-01
    • 1970-01-01
    • 2011-12-03
    • 2020-09-10
    • 1970-01-01
    • 1970-01-01
    • 2019-06-29
    • 1970-01-01
    相关资源
    最近更新 更多