java - 需要使用mockito测试apache poi excel

标签 java spring junit apache-poi 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);
  }

最佳答案

使用您提供的代码,我在这一行重现了 NPE ...

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

...因为虽然被 mock Row指定此模拟未指示返回 Cell调用 createCell .

这可以被 mock 如下:

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。

关于java - 需要使用mockito测试apache poi excel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47321211/

相关文章:

java - 模拟 jooq 选择请求

java - 将哈希表中的哈希表拆分为两个单独的哈希表

java - 突出显示 JTree 节点在幕后工作,但不直观

java - 通过 Spring data.sql 文件生成示例数据库数据

java - 如何在 Spring 中将 Retryable 和 CircuitBreaker 结合在一起?

java - 使用 DBUnit/Junit 测试我的存储库层,我应该手动构建方案还是自动化它?有什么优点?

java - 为什么我的 JUnit 测试文件是否存在不起作用?

java - 按下按钮时没有任何反应

java - 如何在 JavaFX 中创建图例(图表边框中的文本)

java - 使用 Spring-Test-MVC 对 Spring-Security 进行单元测试 - 集成 FilterChain/ServletFilter