我正在使用 commons-fileupload 的框架中工作。
现在我需要编写单元测试类。我的疑问是如果 ServletFileUpload 不是接口,如何编写模拟测试?还有另一种方法可以测试我的课程吗?
昨天我使用 mockito 为 Servlet Parts 编写了单元测试,这很容易。但我想不出如何为 commons-fileupload 编写测试。
我正在使用 commons-fileupload 的框架中工作。
现在我需要编写单元测试类。我的疑问是如果 ServletFileUpload 不是接口,如何编写模拟测试?还有另一种方法可以测试我的课程吗?
昨天我使用 mockito 为 Servlet Parts 编写了单元测试,这很容易。但我想不出如何为 commons-fileupload 编写测试。
您可以使用 Commons HTTPClient 来构建多部分流:
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.apache.http.HttpEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ServletFileUploadMock {
public static class FileUpload {
private final String filename;
private final String mimeType;
private final byte[] contents;
public FileUpload(String filename, String mimeType, byte[] contents) {
this.filename = filename;
this.mimeType = mimeType;
this.contents = contents;
}
}
public static HttpServletResponse mockServletFileUpload(HttpServlet servlet, List<FileUpload> files,
Map<String, String> queryParams) throws IOException, ServletException {
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
for (FileUpload f : files) {
builder = builder.addBinaryBody(f.filename, f.contents, ContentType.create(f.mimeType), f.filename);
}
HttpEntity entity = builder.build();
ByteArrayOutputStream os = new ByteArrayOutputStream();
entity.writeTo(os);
ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
HttpServletRequest mockRequest = mock(HttpServletRequest.class);
when(mockRequest.getMethod()).thenReturn("POST");
when(mockRequest.getContentType()).thenReturn(entity.getContentType().getValue());
when(mockRequest.getContentLength()).thenReturn((int)entity.getContentLength());
when(mockRequest.getInputStream()).thenReturn(new MockServletInputStream(is));
// Mock query params
for (Entry<String, String> p : queryParams.entrySet()) {
when(mockRequest.getParameter(p.getKey())).thenReturn(p.getValue());
}
HttpServletResponse mockResponse = mock(HttpServletResponse.class);
servlet.service(mockRequest, mockResponse);
return mockResponse;
}
public static class MockServletInputStream extends ServletInputStream {
private final InputStream delegate;
public MockServletInputStream(InputStream delegate) {
this.delegate = delegate;
}
@Override
public int read() throws IOException {
return delegate.read();
}
}
}
您可以回到基础并通过包装或扩展和覆盖来手动滚动您的模拟对象。有时更容易不依赖于模拟框架来处理所有事情。
我会考虑将您的 FileUpload 调用包装在另一层中。虽然这听起来有点矫枉过正,但它可以让您非常快速地切换上传库,并增加了更好地对您的调用进行单元测试的能力......看起来您正在将您的应用程序与 commons-fileupload 紧密耦合......