需要使用mockito测试apache poi excel

时间:2017-11-16 03:43:13

标签: java spring junit apache-poi mockito

我编写了一个基于传递数据创建工作簿的类。我现在正在编写mockito测试来测试我的方法。我不允许使用powermock。以下是代码段。

public class TalkDetailsToExcel extends AbstractXlsView {
    private static final ResourceBundle RESOURCE_BUNDLE = MessageResource.getResourceBundle();

    /**
     * Builds the {@link Workbook} containing {@link Talk} details and adds to the {@link Sheet}.
     *
     * @param model               the {@link Map} containing the {@link List} of {@link Talk}.
     * @param workbook            the Excel {@link Workbook} to which {@link Talk} needs to be added.
     * @param httpServletRequest  the {@link HttpServletRequest}
     * @param httpServletResponse the {@link HttpServletResponse}
     * @throws Exception          when adding talk details to workbook.
     */
    @Override
    protected void buildExcelDocument(Map<String, Object> model, Workbook workbook, HttpServletRequest httpServletRequest,
                                      HttpServletResponse httpServletResponse) throws Exception {
        final String talkListName = "talkList";
        final String fileName = "Talk Details.xls";

        httpServletResponse.setHeader("Content-Disposition", "attachment; filename=" + fileName);
        List<Talk> talkList = (List<Talk>) model.get(talkListName);
        Sheet sheet = createAndReturnSheetFromWorkbook(workbook);
        addTalkDetailsToSheet(talkList, sheet);
    }

    /**
     * Creates data cells to the {@link Sheet}.
     *
     * @param talkList the {@link List} of {@link Talk} objects.
     * @param sheet    the {@link Sheet} to which {@link Talk} details need to add.
     */
    @VisibleForTesting
    void addTalkDetailsToSheet(List<Talk> talkList, Sheet sheet) {
        Verifier.verifyNotNull(talkList, RESOURCE_BUNDLE.getString(MessageResource.SHEET_NULL));
        Verifier.verifyNotEmpty(talkList, RESOURCE_BUNDLE.getString(MessageResource.WORKBOOK_NULL));
        Verifier.verifyNotNull(sheet, RESOURCE_BUNDLE.getString(MessageResource.WORKBOOK_NULL));

        int rowCount = 1;
        for (Talk talk : talkList) {
            Row talkRow = sheet.createRow(rowCount++);
            talkRow.createCell(0).setCellValue(talk.getConference().getName());
            talkRow.createCell(1).setCellValue(talk.getTitle());
            talkRow.createCell(2).setCellValue(talk.getSpeaker());
            talkRow.createCell(3).setCellValue(talk.getCernerId());
            talkRow.createCell(4).setCellValue(String.valueOf(talk.getDifficultyLevel()));
            talkRow.createCell(5).setCellValue(talk.getDateTimeStr());
        }
    }

    /**
     * Creates and returns an empty {@link Sheet} containing header {@link Row}.
     *
     * @param workbook       the {@link Workbook} for which {@link Sheet} needs to be created.
     * @return {@link Sheet} containing the header {@link Row}.
     */
    public Sheet createAndReturnSheetFromWorkbook(Workbook workbook) {
        Verifier.verifyNotNull(workbook, RESOURCE_BUNDLE.getString(MessageResource.WORKBOOK_NULL));

        final String sheetName = "Conference Details";
        final String conferenceName = "Conference";
        final String talkTitle = "Talk";
        final String speakerName = "Speaker";
        final String cernerIdOfSpeaker = "Cerner Id";
        final String difficultyLevel = "Difficulty";
        final String dateTimeOfTalk = "Date Time";

        Sheet sheet = workbook.createSheet(sheetName);
        Row header = sheet.createRow(0);
        header.createCell(0).setCellValue(conferenceName);
        header.createCell(1).setCellValue(talkTitle);
        header.createCell(2).setCellValue(speakerName);
        header.createCell(3).setCellValue(cernerIdOfSpeaker);
        header.createCell(4).setCellValue(difficultyLevel);
        header.createCell(5).setCellValue(dateTimeOfTalk);
        return sheet;
    }
}

以下是我到目前为止编写junit的代码片段,我无法使用createRow模拟行。问题是Row总是为null并且测试抛出空指针异常。任何建议都非常感谢。

   /**
   * Tests {@link TalkDetailsToExcel#createAndReturnSheetFromWorkbook(Workbook)} returns a {@link
   * Sheet}
   */
  @Test
  public void testCreateAndReturnSheetFromWorkbookReturnsSheet() {
    Workbook mockWorkbook = mock(Workbook.class);
    Sheet mockSheet = mock(Sheet.class);
    Row mockRow = mock(Row.class);
    doReturn(mockSheet).when(mockWorkbook).createSheet();
    doReturn(mockRow).when(mockSheet.createRow(anyInt()));

    Sheet sheet = mockTalkDetailsToExcel.createAndReturnSheetFromWorkbook(mockWorkbook);
  }

1 个答案:

答案 0 :(得分:3)

使用您提供的代码,我在此行复制了一份NPE ......

talkRow.createCell(0).setCellValue(...)

...因为虽然指定了模拟Row,但未指示此模拟在Cell的调用时返回createCell

这可以嘲笑如下:

when(mockSheet.createRow(anyInt())).thenReturn(mockRow);
when(mockRow.createCell(anyInt())).thenReturn(mockCell);

因此,测试可以改写为:

Workbook mockWorkbook = mock(Workbook.class);
Sheet mockSheet = mock(Sheet.class);
Row mockRow = mock(Row.class);
Cell mockCell = mock(Cell.class);
when(mockWorkbook.createSheet("Conference Details")).thenReturn(mockSheet);
when(mockSheet.createRow(0)).thenReturn(mockRow);
when(mockSheet.createRow(anyInt())).thenReturn(mockRow);
when(mockRow.createCell(anyInt())).thenReturn(mockCell);

Sheet sheet = mockTalkDetailsToExcel.createAndReturnSheetFromWorkbook(mockWorkbook);

这解决了NPE。