spring 3.2.4 中的 PowerMockito 模拟静态测试控制器
PowerMockito mocking static testing controller in spring 3.2.4
我正在执行一些 mockito 测试,但是我在 1 class 中遇到了一些问题,它有一个静态方法,我在测试的 setUp() 方法中模拟了 class
有这个class:
public class ResponseFileWriteHelper {
public static void write(HttpServletResponse response, String fileName, StreamWriter writer) {
response.setHeader("Cache-Control", "");
response.setContentType("application/octet");
if (!StringUtils.isBlank(fileName)) {
response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
}
try {
writer.doWrite(response.getOutputStream());
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
}
这里是我要测试的控制器:
public class ManageDeviceController extends SimpleFormController {
...
private void generateDevicexBeneficiaryList(
Collection<Integer> selectedYears, PriorityAreaKey priorityAreaKey, Language language, Collection<DeviceStatus> statuses, HttpServletResponse response) throws Exception {
final List<ReportItem> reportItems
= DeviceListReportService.getDevicesxBeneficiaryForYears(selectedYears, priorityAreaKey, language, statuses);
ResponseFileWriteHelper.write(response, "DevicesxBeneficiaryList.xls", new StreamWriter() {
@Override
public void doWrite(OutputStream outputStream) throws Exception {
DeviceListExcelReportRendererBuilder.build().renderToStream(
reportItems, outputStream);
}});
}
}
这里测试class
@RunWith(MockitoJUnitRunner.class)
public class SelectDeviceListExcelReportControllerTest {
public void setUp() {
PowerMockito.mockStatic (ResponseFileWriteHelper.class);
EDeviceSessionContext.getInstance().setSession(httpSession);
when(request.getSession()).thenReturn(httpSession);
when(request.getLocale()).thenReturn(Locale.ENGLISH);
messages.initialize();
}
@SuppressWarnings("unchecked")
@Test
@PrepareForTest(ResponseFileWriteHelper.class)
public void successTest() throws Exception {
TableItemBuilder tableItemBuilder =
new TableItemBuilder(new LabelCellItem("success.test"));
List<ReportItem> expectedData = Arrays.asList(
new ReportItem("success.test",Arrays.asList(tableItemBuilder.getTableItem())));
final ByteArrayOutputStream resultData = new ByteArrayOutputStream();
ServletOutputStream output = new ServletOutputStream() {
@Override
public void write(int val) throws IOException {
resultData.write(val);
}
};
when(response.getOutputStream()).thenReturn(output);
when(deviceListReportService.getDevicesxBeneficiaryForYears(
any(List.class), any(PriorityAreaKey.class), any(Language.class), any(Collection.class))).thenReturn(expectedData);
doCall();
//assertArrayEquals(expectedData, resultData);
}
}
但是测试崩溃了,因为 java.lang.NullPointer 这里:
ResponseFileWriteHelper.write(response, "DevicesxBeneficiaryList.xls", new StreamWriter() {
@PrepareForTest()
在你的测试 class 中只能与 PowerMockRunner.class
一起使用,所以你需要在你的测试 class 中添加 @RunWith(PowerMockRunner.class)
。
但是另一个问题是你真的想使用 SpringJUnit4ClassRunner.class
作为你的测试运行器,感谢 powermock 已经意识到这个问题,它提供了 PowerMockRunnerDelegate
注释来实现它。
工作副本将是这样的:
@WebAppConfiguration
@ContextConfiguration(locations = {
"......"
)
@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)
@PowerMockIgnore("javax.management.*") // to specify that all classes under the specified package be loaded by the system class loader
@PrepareForTest({Static.class})
public void ControllerTest {
public void testMockStatic() {
PowerMockito.mockStatic(Static.class);
......
}
}
我正在执行一些 mockito 测试,但是我在 1 class 中遇到了一些问题,它有一个静态方法,我在测试的 setUp() 方法中模拟了 class
有这个class:
public class ResponseFileWriteHelper {
public static void write(HttpServletResponse response, String fileName, StreamWriter writer) {
response.setHeader("Cache-Control", "");
response.setContentType("application/octet");
if (!StringUtils.isBlank(fileName)) {
response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
}
try {
writer.doWrite(response.getOutputStream());
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
}
这里是我要测试的控制器:
public class ManageDeviceController extends SimpleFormController {
...
private void generateDevicexBeneficiaryList(
Collection<Integer> selectedYears, PriorityAreaKey priorityAreaKey, Language language, Collection<DeviceStatus> statuses, HttpServletResponse response) throws Exception {
final List<ReportItem> reportItems
= DeviceListReportService.getDevicesxBeneficiaryForYears(selectedYears, priorityAreaKey, language, statuses);
ResponseFileWriteHelper.write(response, "DevicesxBeneficiaryList.xls", new StreamWriter() {
@Override
public void doWrite(OutputStream outputStream) throws Exception {
DeviceListExcelReportRendererBuilder.build().renderToStream(
reportItems, outputStream);
}});
}
}
这里测试class
@RunWith(MockitoJUnitRunner.class)
public class SelectDeviceListExcelReportControllerTest {
public void setUp() {
PowerMockito.mockStatic (ResponseFileWriteHelper.class);
EDeviceSessionContext.getInstance().setSession(httpSession);
when(request.getSession()).thenReturn(httpSession);
when(request.getLocale()).thenReturn(Locale.ENGLISH);
messages.initialize();
}
@SuppressWarnings("unchecked")
@Test
@PrepareForTest(ResponseFileWriteHelper.class)
public void successTest() throws Exception {
TableItemBuilder tableItemBuilder =
new TableItemBuilder(new LabelCellItem("success.test"));
List<ReportItem> expectedData = Arrays.asList(
new ReportItem("success.test",Arrays.asList(tableItemBuilder.getTableItem())));
final ByteArrayOutputStream resultData = new ByteArrayOutputStream();
ServletOutputStream output = new ServletOutputStream() {
@Override
public void write(int val) throws IOException {
resultData.write(val);
}
};
when(response.getOutputStream()).thenReturn(output);
when(deviceListReportService.getDevicesxBeneficiaryForYears(
any(List.class), any(PriorityAreaKey.class), any(Language.class), any(Collection.class))).thenReturn(expectedData);
doCall();
//assertArrayEquals(expectedData, resultData);
}
}
但是测试崩溃了,因为 java.lang.NullPointer 这里:
ResponseFileWriteHelper.write(response, "DevicesxBeneficiaryList.xls", new StreamWriter() {
@PrepareForTest()
在你的测试 class 中只能与 PowerMockRunner.class
一起使用,所以你需要在你的测试 class 中添加 @RunWith(PowerMockRunner.class)
。
但是另一个问题是你真的想使用 SpringJUnit4ClassRunner.class
作为你的测试运行器,感谢 powermock 已经意识到这个问题,它提供了 PowerMockRunnerDelegate
注释来实现它。
工作副本将是这样的:
@WebAppConfiguration
@ContextConfiguration(locations = {
"......"
)
@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)
@PowerMockIgnore("javax.management.*") // to specify that all classes under the specified package be loaded by the system class loader
@PrepareForTest({Static.class})
public void ControllerTest {
public void testMockStatic() {
PowerMockito.mockStatic(Static.class);
......
}
}