【问题标题】:Write a unit test for downloading a file编写用于下载文件的单元测试
【发布时间】:2014-07-06 07:25:42
【问题描述】:

目前我写了一个小的 downloadService 让我们用户下载一个文件(目前只有 excel)。该代码可以正常工作,但是我不知道如何为其编写单元测试。这是我的代码:

package com.pzm.service;

import com.pzm.model.UserBillingsMock;
import com.pzm.model.report.ExcelReport;
import com.pzm.model.report.Report;
import com.pzm.model.report.ReportFactory;
import org.springframework.stereotype.Repository;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

/**
 * Created by akfaz on 6/26/14.
 */

@Repository
public class DownloadService {

    private Report report;
    private List<UserBillings> userBillings;

    public void setBill(List<UserBillings> userBillings) {
        this.userBillings = userBillings;
    }

    public void download(HttpServletResponse response, String reportType) {

        response.setContentType("application/vnd.ms-excel");
        response.setHeader("Content-Disposition", "attachment; filename=MyExcel.xls");

        report = new ReportFactory().create(reportType, userBillings);
        saveFile(response, report);
    }

    private void saveFile(HttpServletResponse response, Report report) {
        try {
            ServletOutputStream outputStream = response.getOutputStream();
            report.write(outputStream);
            outputStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

单元测试 - 尝试使用 Mockito,但出现异常:

单元测试:

package com.pzm.service;

import junit.framework.TestCase;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import javax.servlet.http.HttpServletResponse;
import static org.mockito.Mockito.*;

/**
 * Created by akfaz on 7/5/14.
 */
public class DownloadServiceTest extends TestCase{

    HttpServletResponse mockResponse;
    DownloadService downloadService;

    @Before
    public void setUp() throws Exception {
        mockResponse = mock(HttpServletResponse.class);
        downloadService = new DownloadService();
    }

    @Test
    public void testDownload() throws Exception {
        downloadService.download(mockResponse, "xls");

        verify(mockResponse).getContentType();
    }
}

还有例外:

org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException: Fail to save: an error occurs while saving the package : null
    at org.apache.poi.openxml4j.opc.ZipPackage.saveImpl(ZipPackage.java:500)
    at org.apache.poi.openxml4j.opc.OPCPackage.save(OPCPackage.java:1417)
    at org.apache.poi.POIXMLDocument.write(POIXMLDocument.java:179)
    at com.pzm.model.report.ExcelReport.write(ExcelReport.java:46)
    at com.pzm.service.DownloadService.saveFile(DownloadService.java:40)
    at com.pzm.service.DownloadService.download(DownloadService.java:34)
    at com.pzm.service.DownloadServiceTest.testDownload(DownloadServiceTest.java:32)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:83)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:74)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:202)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:65)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: java.lang.NullPointerException
    at java.util.zip.DeflaterOutputStream.<init>(DeflaterOutputStream.java:84)
    at java.util.zip.DeflaterOutputStream.<init>(DeflaterOutputStream.java:142)
    at java.util.zip.ZipOutputStream.<init>(ZipOutputStream.java:118)
    at java.util.zip.ZipOutputStream.<init>(ZipOutputStream.java:104)
    at org.apache.poi.openxml4j.opc.ZipPackage.saveImpl(ZipPackage.java:433)
    ... 28 more

【问题讨论】:

  • 你在模拟一个 HttpServletResponse。因此,在此模拟响应上调用 getOutputStream() 将返回 null,除非您在调用此方法时告诉模拟返回一个 OutputStream。
  • 您可以尝试使用Mockito.spy() 而不是Mockito.mock() 来创建您的mockResponse 吗?

标签: java unit-testing junit mockito


【解决方案1】:

当你创建一个模拟对象时

mockResponse = mock(HttpServletResponse.class);

默认情况下,所有具有引用类型的方法都返回类型(减去一些特殊情况)返回null

所以这个sn-p中getOutputStream()的返回值

ServletOutputStream outputStream = response.getOutputStream();

null

您需要设定期望并指定返回值。

when(mockResponse.getOutputStream().thenReturn(/* the value to return when that method is invoked */);

这叫stubbing

【讨论】:

  • +1 这是正确的做法。顺便说一句,您的第一句话并不完全正确 - 有一些引用类型的 Mockito 默认不为空,例如集合。
  • @DavidWallace 任何Collection 子类型?我不知道。
  • 嗯,是的,您在回答中提到的“少数特殊情况”如下。 (1) 返回任何包装器类型的方法将默认返回 0 或 false。 (2) 返回Collection 的任何子类型的方法将默认返回一个空集合。 (3) 标准toString的任何实现都会默认返回mock的名字。 (4) 任何标准compareTo的实现都会默认返回1。
猜你喜欢
  • 2012-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-20
  • 2020-05-28
  • 1970-01-01
相关资源
最近更新 更多