【问题标题】:Spring MockMVC test with JSON content is throwing NullPointerException from Spring code带有 JSON 内容的 Spring MockMVC 测试从 Spring 代码中抛出 NullPointerException
【发布时间】:2014-12-04 19:37:15
【问题描述】:

我有一个小型 Spring MVC 项目。我正在为它编写 MockMvc 测试。它们中的大多数都可以工作,但是这个(我尝试过的第一个使用纯 JSON 正文的)给我带来了麻烦。我不断从 Spring 内部得到 NullPointerException。我尝试通过它进行调试,但最终用完了附加的 Spring 源代码而没有更接近答案。

我的 JSON 块是从实时用户测试中捕获的,效果很好。但是在测试中,它会抛出 NPE。如果我将 JSON 块修改为格式错误(IE,在某处添加一个额外的逗号),那么它会按预期抛出 400 Bad Request。去掉多余的逗号,回到 NPE。使块无效(IE,使我的域对象中标记为@NotNull 的字段为空)不会给出预期的 400 错误请求。它只保留在 NPE 中。

到目前为止,我所有的其他测试都是针对只使用查询字符串参数的控制器,并且运行良好。另外,我有一个由于我们客户方面的浏览器限制,必须将其 JSON 嵌入到 POST 参数(IE,“json =”{blah:blah}“)中,我将其取出并手动解析。这也很好.

控制器:

@RestController
public class SaveController {

    @Autowired
    private MyDao myDao;

    @RequestMapping(value = "/path/to/controller", method = RequestMethod.POST)
    @PreAuthorize("hasAnyRole('myRole', 'myAdminRole')")
    public void updateThing(@Valid @RequestBody MyThing myThing) throws IOException {
        myDao.updateMyThing(myThing);
    }
}

基础测试类:

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = {TestDataAccessConfiguration.class, TestApplicationConfiguration.class})
public abstract class AbstractSpringTestCase {
    @Autowired
    protected WebApplicationContext wac;

    protected MockMvc mockMvc;

    @Before
    public void setUp() throws Exception {
        mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
        MockitoAnnotations.initMocks(this);
    }
}

测试:

public class SaveControllerTest extends AbstractSpringTestCase {
    @Mock
    private MyDao myDao;

    @InjectMocks
    @Autowired
    private SaveController classUnderTest;

    private static final JSON = "<a big JSON string captured from (working) production>";

    @Test
    public void testHappyPath() throws Exception {
        mockMvc.perform(post("/path/to/controller")
            .contentType(MediaType.APPLICATION_JSON)
            .content(JSON))
            .andExpect(status().isOk());
    }
}

堆栈跟踪:

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NullPointerException
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:978)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:868)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
    at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:62)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
    at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:170)
    at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:137)
    at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:145)
    at SaveControllerTest.testHappyPath(SaveControllerTest.java)

【问题讨论】:

  • 请发布堆栈跟踪的其余部分。

标签: java json spring spring-mvc


【解决方案1】:

为了使用 Spring MockMvc 发送请求正文,您必须将 @RequestBody 对象映射为 json 字符串。

这是一个例子:

SingupController:

@PostMapping("/signup")
public @ResponseBody
RealityKeeper createUser(@RequestBody SignupRequest signupRequest) {
    System.out.println("SignupRequest: " + signupRequest);
    String password = signupRequest.getPassword();
    String username = signupRequest.getUsername();
    String encoded = passwordEncoder.encode(password);
    RealityKeeper realityKeeper = new RealityKeeper(username, encoded);
    return repository.save(realityKeeper);
}

SignupControllerTest:

@Test
public void createUser() throws Exception {
    SignupRequest signupRequest = new SignupRequest("foo", "bar");

    ObjectMapper mapper = new ObjectMapper();
    mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, false);
    ObjectWriter ow = mapper.writer().withDefaultPrettyPrinter();
    String requestJson=ow.writeValueAsString(signupRequest);

    mockMvc.perform(post("/api/signup")
            .contentType(MediaType.APPLICATION_JSON)
            .content(requestJson))
            .andExpect(MockMvcResultMatchers.status().isOk());

}

使用 jackson 的对象映射器,您可以将 pojo 转换为 json 字符串并将其传递给 mockMvc 内容方法。

希望对你有帮助

【讨论】:

    猜你喜欢
    • 2019-07-30
    • 2022-01-04
    • 2016-11-30
    • 2013-12-28
    • 2019-07-21
    • 1970-01-01
    • 2018-10-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多