使用JSON内容的Spring MockMVC测试从Spring代码中抛出NullPointerException

时间:2014-12-04 19:37:16

标签: java json spring spring-mvc

我有一个小型的Spring MVC项目。我正在为它编写MockMvc测试。他们中的大多数都有效,但是这个(我用普通的JSON机构试过的第一个)给了我麻烦。我一直在Spring内部得到一个NullPointerException。我尝试通过它进行调试,但最终耗尽了附加的Spring源代码而没有得到更接近答案。

我的JSON块是从实时用户测试中捕获的,它运行正常。但在测试中,它会引发NPE。如果我修改JSON块以使其格式不正确(IE,在某处添加额外的逗号),那么它会按预期抛出400 Bad Request。删除额外的逗号,返回NPE。使块无效(IE,使字段为null,在我的域对象中标记为@NotNull)不会给出预期的400 Bad Request。它只是留在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)

1 个答案:

答案 0 :(得分:0)

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

这是一个例子:

SingupController:

class SampleEditor : public QGraphicsView {
   Q_OBJECT
   bool m_activeDrag = false;
   SignalingBoxItem m_box;
   QPointF m_dragStart;

  public:
   SampleEditor(QGraphicsScene *scene) : QGraphicsView(scene) {
      scene->addItem(&m_box);
      connect(&m_box, &SignalingBoxItem::rectChanged, this, &SampleEditor::rectChanged);
   }
   Q_SIGNAL void rectChanged(const QRectF &);
   void mousePressEvent(QMouseEvent *event) override {
      QGraphicsView::mousePressEvent(event);
      if (event->button() == Qt::RightButton) {
         m_dragStart = m_box.mapFromScene(mapToScene(event->pos()));
         m_activeDrag = true;
         m_box.show();
         m_box.setRect({m_dragStart, m_dragStart});
         event->accept();
      }
   }
   void mouseMoveEvent(QMouseEvent *event) override {
      QGraphicsView::mouseMoveEvent(event);
      if (m_activeDrag) {
         m_box.setRect({m_dragStart, m_box.mapFromScene(mapToScene(event->pos()))});
         event->accept();
      }
   }
   void mouseReleaseEvent(QMouseEvent *event) override {
      QGraphicsView::mouseReleaseEvent(event);
      if (m_activeDrag && event->button() == Qt::RightButton) {
         event->accept();
         m_activeDrag = false;
      }
   }
   void resizeEvent(QResizeEvent *event) override {
      QGraphicsView::resizeEvent(event);
      scene()->setSceneRect(contentsRect());
   }
#if SOLUTIONS
   void selectSolution(int index) { m_box.selectSolution(index); }
#endif
};

SignupControllerTest:

int main(int argc, char *argv[]) {
   QApplication a(argc, argv);
   QWidget ui;
   QGridLayout layout{&ui};
   QGraphicsScene scene;
   SampleEditor editor(&scene);
   QComboBox sel;
   QLabel status;
   layout.addWidget(&editor, 0, 0, 1, 2);
   layout.addWidget(&sel, 1, 0);
   layout.addWidget(&status, 1, 1);
   sel.addItems({
      "Original (Movable SignalingBoxItem)",
#if HAS_SOLUTION(1)
          "Movable SizeGripItem",
#endif
#if HAS_SOLUTION(2)
          "Reimplemented HandleItem",
#endif
#if HAS_SOLUTION(3)
          "Filtering SizeGripItem",
#endif
   });
   sel.setCurrentIndex(-1);
#if SOLUTIONS
   QObject::connect(&sel, QOverload<int>::of(&QComboBox::currentIndexChanged),
                    [&](int index) { editor.selectSolution(index); });
#endif
   QObject::connect(&editor, &SampleEditor::rectChanged, &status,
                    [&](const QRectF &rect) {
                       QString s;
                       QDebug(&s) << rect;
                       status.setText(s);
                    });
   sel.setCurrentIndex((sel.count() > 1) ? 1 : 0);
   ui.setMinimumSize(640, 480);
   ui.show();
   return a.exec();
}
#include "main.moc"

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

希望这会有所帮助