spring-boot - 意外异常,预期但是是
问题描述
我正在尝试实现邮件服务(org.springframework.mail.javamail),功能工作得非常好,但是在使用mockito5 而不是 powermockito编写单元测试用例时,我无法涵盖 catch(MessagingException e) and catch(IOException e)
这是一段实现代码UsageReportBillingMailService.java
@Service
@Slf4j
public class UsageReportBillingMailService {
@Value("${mail_receivers.mail_to:''}")
private String[] mailToList;
@Autowired
private JavaMailSender emailSender;
@Autowired
private IUsageReportBillingRepository billingRepository;
public void send(String period) {
try {
log.info("{} Getting usage billing report from DB ", UsageReportConstants.USAGE_REPORT_BILLING_MAIL_SERVICE_LOG);
UsageReportBilling billingReportForPeriod = billingRepository.findByPeriod(period);
if (billingReportForPeriod == null) {
log.error("{} Cannot get the report from DB ", UsageReportConstants.USAGE_REPORT_BILLING_MAIL_SERVICE_LOG);
throw new ReportNotFoundException(UsageReportConstants.REPORT_NOT_FOUND);
}
String reportHeader = UsageReportConstants.BILLING_REPORT_CSV_HEADER;
String reportContent = billingReportForPeriod.getPeriod() + UsageReportConstants.COMMA +
billingReportForPeriod.getDeviceCount() + UsageReportConstants.COMMA +
billingReportForPeriod.getStorageUsed() + UsageReportConstants.COMMA +
billingReportForPeriod.getApiSuccessCount() + UsageReportConstants.COMMA +
billingReportForPeriod.getApiFailCount() + UsageReportConstants.COMMA +
billingReportForPeriod.getEventCount();
File attachmentFile = generateAttachmentFile(UsageReportConstants.BILLING_REPORT_FILE_NAME_PREFIX + period, UsageReportConstants.CSV_FILE_EXT, reportHeader.concat("\n" + reportContent));
prepareMail(mailToList, UsageReportConstants.MAIL_FROM, UsageReportConstants.MAIL_SUBJECT + " " + period, UsageReportConstants.MAIL_BODY + " " + period, attachmentFile);
} catch (IOException e) {
log.error("{} Cannot create attachment file ", UsageReportConstants.USAGE_REPORT_BILLING_MAIL_SERVICE_LOG);
} catch (MessagingException e) {
log.error("{} if multipart creation failed ", UsageReportConstants.USAGE_REPORT_BILLING_MAIL_SERVICE_LOG);
}
}
private File generateAttachmentFile(String fileName, String fileType, String fileContent) throws IOException {
log.info("{} Generating File from content for mail attachment ", UsageReportConstants.USAGE_REPORT_BILLING_MAIL_SERVICE_LOG);
byte[] outputBytes = fileContent.getBytes(StandardCharsets.UTF_8);
File tempFile = File.createTempFile(fileName, fileType, null);
FileOutputStream fos = new FileOutputStream(tempFile);
fos.write(outputBytes);
return tempFile;
}
private void prepareMail(String[] toList, String from, String mailSubject, String mailBody, File attachment) throws MessagingException {
log.info("{} Preparing mail and sending to listed recipient ", UsageReportConstants.USAGE_REPORT_BILLING_MAIL_SERVICE_LOG);
MimeMessage message = emailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setSubject(mailSubject);
helper.setText(mailBody);
helper.setTo(toList);
helper.setFrom(from);
helper.addAttachment(attachment.getName(), attachment);
emailSender.send(message);
}
}
我试图在 Junit 测试用例中涵盖的内容UsageReportBillingMailServiceTest.java
@RunWith(SpringRunner.class)
public class UsageReportBillingMailServiceTest {
@InjectMocks
private UsageReportBillingMailService usageReportBillingMailService;
@Mock
private UsageReportBilling usageReportBilling;
@Mock
private JavaMailSender emailSender;
@Mock
private IUsageReportBillingRepository usageReportBillingRepository;
private String period = "2020-06";
@Test
public void verifySendEmail() {
MimeMessage mimeMessage = Mockito.mock(MimeMessage.class);
ReflectionTestUtils.setField(usageReportBillingMailService, "mailToList", new String[]{"info@testmail.com", "info@testmail.com"});
Mockito.when(usageReportBillingRepository.findByPeriod(period)).thenReturn(buildUsageReportBilling());
Mockito.when(emailSender.createMimeMessage()).thenReturn(mimeMessage);
usageReportBillingMailService.send(period);
Assert.assertNull(null);
}
@Test(expected = ReportNotFoundException.class)
public void verifySendEmailWhenReportNotFoundExceptionThrown() {
MimeMessage mimeMessage = Mockito.mock(MimeMessage.class);
Mockito.when(usageReportBillingRepository.findByPeriod("2029-01")).thenReturn(null);
usageReportBillingMailService.send(period);
Assert.assertNull(" ReportNotFound Exception Expected ");
}
/*
// this is not working
@Test(expected = IOException.class)
public void verifySendEmailWhenIOExceptionThrown() throws IOException {
FileOutputStream fos = Mockito.mock(FileOutputStream.class);
ReflectionTestUtils.setField(usageReportBillingMailService, "mailToList", new String[]{"info@testmail.com", "info@testmail.com"});
Mockito.when(usageReportBillingRepository.findByPeriod(period)).thenReturn(buildUsageReportBilling());
Mockito.doThrow(new IOException("this")).when(usageReportBillingMailService).send(period);
usageReportBillingMailService.send(period);
Assert.assertNull(" IOException Expected ");
}
// this is not working
@Test(expected = MessagingException.class)
public void verifySendEmailWhenMessagingExceptionThrown() throws MessagingException {
MimeMessage mimeMessage = Mockito.mock(MimeMessage.class);
ReflectionTestUtils.setField(usageReportBillingMailService, "mailToList", new String[]{"info@testmail.com", "info@testmail.com"});
Mockito.when(usageReportBillingRepository.findByPeriod(period)).thenReturn(buildUsageReportBilling());
Mockito.when(emailSender.createMimeMessage()).thenReturn(mimeMessage);
Mockito.doThrow(new MessagingException("this")).when(usageReportBillingMailService).send(period);
usageReportBillingMailService.send(period);
Assert.assertNull(" MessagingException Expected ");
}
*/
private UsageReportBilling buildUsageReportBilling() {
UsageReportBilling billingReport = new UsageReportBilling();
billingReport.setPeriod(period);
billingReport.setDeviceCount(100L);
billingReport.setStorageUsed(10000L);
billingReport.setApiSuccessCount(1000L);
billingReport.setApiFailCount(10L);
billingReport.setEventCount(0L);
return billingReport;
}
}
解决方案
MessagingException
MimeMessageHelper
在创建对象时抛出。因此,您可以创建一个方法来创建此对象并模拟该方法调用以引发此异常。
UsageReportBillingMailService current = this;
private void prepareMail(String[] toList, String from, String mailSubject, String mailBody, File attachment) throws MessagingException {
log.info("{} Preparing mail and sending to listed recipient ", UsageReportConstants.USAGE_REPORT_BILLING_MAIL_SERVICE_LOG);
MimeMessage message = emailSender.createMimeMessage();
MimeMessageHelper helper = current.createMimeMessageHelper(message, true);
helper.setSubject(mailSubject);
helper.setText(mailBody);
helper.setTo(toList);
helper.setFrom(from);
helper.addAttachment(attachment.getName(), attachment);
emailSender.send(message);
}
MimeMessageHelper createMimeMessageHelper(MimeMessage message, boolean multipart) {
return new MimeMessageHelper(message, multipart);
}
在测试中
when(mocked.createMimeMessageHelper(any(MimeMessage.class), anyBoolean())
.thenThrow(new MessagingException("test"));
FieldSetter.setField(usageReportBillingMailServiceInstance, UsageReportBillingMailService.class.getDeclaredField("current"), mocked);
usageReportBillingMailServiceInstance.prepareMessage(...)
推荐阅读
- javascript - d3 数据解析/转换(从长到宽)
- css - 如何将我的单个菜单背景与 wordpress 中的 css 垂直对齐(垂直对齐中间不起作用)
- angular - 从路由器 URL 获取 ID
- vue.js - HighCharts Vue JS - CSV 键
- php - 使用 php 在文本文件中搜索
- reactjs - 如何设置子组件而不在父组件中渲染?
- ios - 通过短信发送和接收 iOS 应用数据
- php - 如何允许用户从 WordPress 网页搜索我的数据库
- php - [Route: 缺少必需的参数:
- php - get_post_meta 和 add_post_meta 在 wordpress 中不起作用