在Spring Boot应用程序中测试邮件代码

logo-spring-io

在构建Spring Boot应用程序时,您可能会需要添加邮件配置。 实际上,在Spring Boot中配置邮件与在Spring Bootless应用程序中配置邮件没有太大区别。 但是,如何测试邮件配置和提交工作正常? 我们来看一下。

我假设我们有一个引导的简单Spring Boot应用程序。 如果没有,最简单的方法是使用Spring Initializr 。

添加javax.mail依赖项

我们首先将javax.mail依赖项添加到build.gradlecompile 'javax.mail:mail:1.4.1' 。 我们还将需要包含JavaMailSender支持类的Spring Context Support (如果不存在)。 依赖项是: compile("org.springframework:spring-context-support")

基于Java的配置

Spring Boot支持基于Java的配置。 为了添加邮件配置,我们添加了带有@Configuration注释的MailConfiguration类。 这些属性存储在mail.properties (尽管不是必需的)。 可以使用@Value批注将属性值直接注入到bean中:

@Configuration
@PropertySource("classpath:mail.properties")
public class MailConfiguration {@Value("${mail.protocol}")private String protocol;@Value("${mail.host}")private String host;@Value("${mail.port}")private int port;@Value("${mail.smtp.auth}")private boolean auth;@Value("${mail.smtp.starttls.enable}")private boolean starttls;@Value("${mail.from}")private String from;@Value("${mail.username}")private String username;@Value("${mail.password}")private String password;@Beanpublic JavaMailSender javaMailSender() {JavaMailSenderImpl mailSender = new JavaMailSenderImpl();Properties mailProperties = new Properties();mailProperties.put("mail.smtp.auth", auth);mailProperties.put("mail.smtp.starttls.enable", starttls);mailSender.setJavaMailProperties(mailProperties);mailSender.setHost(host);mailSender.setPort(port);mailSender.setProtocol(protocol);mailSender.setUsername(username);mailSender.setPassword(password);return mailSender;}
}

@PropertySource批注使mail.properties可用于通过@Value注入。 注解。 如果未完成,则可能会遇到异常: java.lang.IllegalArgumentException: Could not resolve placeholder '<name>' in string value "${<name>}"

mail.properties

mail.protocol=smtp
mail.host=localhost
mail.port=25
mail.smtp.auth=false
mail.smtp.starttls.enable=false
mail.from=me@localhost
mail.username=
mail.password=

邮件端点

为了能够在我们的应用程序中发送电子邮件,我们可以创建一个REST端点。 我们可以使用Spring的SimpleMailMessage来快速实现此端点。 我们来看一下:

@RestController
class MailSubmissionController {private final JavaMailSender javaMailSender;@AutowiredMailSubmissionController(JavaMailSender javaMailSender) {this.javaMailSender = javaMailSender;}@RequestMapping("/mail")@ResponseStatus(HttpStatus.CREATED)SimpleMailMessage send() {        SimpleMailMessage mailMessage = new SimpleMailMessage();mailMessage.setTo("someone@localhost");mailMessage.setReplyTo("someone@localhost");mailMessage.setFrom("someone@localhost");mailMessage.setSubject("Lorem ipsum");mailMessage.setText("Lorem ipsum dolor sit amet [...]");javaMailSender.send(mailMessage);return mailMessage;}
}

运行应用程序

现在,我们准备运行该应用程序。 如果使用CLI,请输入: gradle bootRun ,打开浏览器并导航到localhost:8080/mail 。 您应该看到的实际上是一个错误,表示邮件服务器连接失败。 如预期的那样。

伪造SMTP服务器

FakeSMTP是带有Java的GUI的免费Fake SMTP服务器,用Java编写,用于测试应用程序中的电子邮件。 我们将使用它来验证提交是否有效。 请下载该应用程序,然后通过调用java -jar fakeSMTP-<version>.jar即可运行它。 启动伪造的SMTP服务器后,启动服务器。

现在,您可以再次调用REST端点,并在Fake SMTP中查看结果!

但是,测试并不是指手动测试! 该应用程序仍然有用,但是我们要自动测试邮件代码。

单元测试邮件代码

为了能够自动测试邮件提交,我们将使用Wiser –一种基于SubEtha SMTP的单元测试邮件的框架/实用程序。 SubEthaSMTP的简单,低级API适用于编写几乎所有类型的邮件接收应用程序。

使用Wiser非常简单。 首先,我们需要向build.gradle添加一个测试依赖build.gradletestCompile("org.subethamail:subethasmtp:3.1.7") 。 其次,我们使用JUnit,Spring和Wiser创建一个集成测试:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
public class MailSubmissionControllerTest {private Wiser wiser;@Autowiredprivate WebApplicationContext wac;private MockMvc mockMvc;@Beforepublic void setUp() throws Exception {wiser = new Wiser();wiser.start();mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();}@Afterpublic void tearDown() throws Exception {wiser.stop();}@Testpublic void send() throws Exception {// actmockMvc.perform(get("/mail")).andExpect(status().isCreated());// assertassertReceivedMessage(wiser).from("someone@localhosts").to("someone@localhost").withSubject("Lorem ipsum").withContent("Lorem ipsum dolor sit amet [...]");}
}

SMTP服务器进行初始化,开始@Before方法和停止@Teardown方法。 发送消息后,将进行断言。 由于框架不提供任何断言,因此需要创建断言。 您将注意到,我们需要对Wiser对象进行操作,该对象提供了已接收消息的列表:

public class WiserAssertions {private final List<WiserMessage> messages;public static WiserAssertions assertReceivedMessage(Wiser wiser) {return new WiserAssertions(wiser.getMessages());}private WiserAssertions(List<WiserMessage> messages) {this.messages = messages;}public WiserAssertions from(String from) {findFirstOrElseThrow(m -> m.getEnvelopeSender().equals(from),assertionError("No message from [{0}] found!", from));return this;}public WiserAssertions to(String to) {findFirstOrElseThrow(m -> m.getEnvelopeReceiver().equals(to),assertionError("No message to [{0}] found!", to));return this;}public WiserAssertions withSubject(String subject) {Predicate<WiserMessage> predicate = m -> subject.equals(unchecked(getMimeMessage(m)::getSubject));findFirstOrElseThrow(predicate,assertionError("No message with subject [{0}] found!", subject));return this;}public WiserAssertions withContent(String content) {findFirstOrElseThrow(m -> {ThrowingSupplier<String> contentAsString = () -> ((String) getMimeMessage(m).getContent()).trim();return content.equals(unchecked(contentAsString));}, assertionError("No message with content [{0}] found!", content));return this;}private void findFirstOrElseThrow(Predicate<WiserMessage> predicate, Supplier<AssertionError> exceptionSupplier) {messages.stream().filter(predicate).findFirst().orElseThrow(exceptionSupplier);}private MimeMessage getMimeMessage(WiserMessage wiserMessage) {return unchecked(wiserMessage::getMimeMessage);}private static Supplier<AssertionError> assertionError(String errorMessage, String... args) {return () -> new AssertionError(MessageFormat.format(errorMessage, args));}public static <T> T unchecked(ThrowingSupplier<T> supplier) {try {return supplier.get();} catch (Throwable e) {throw new RuntimeException(e);}}interface ThrowingSupplier<T> {T get() throws Throwable;}
}

摘要

仅需几行代码,我们就可以自动测试邮件代码。 本文介绍的示例并不复杂,但是它显示了使用SubEtha SMTP和Wiser入门很容易。

您如何测试您的邮件代码?

翻译自: https://www.javacodegeeks.com/2014/09/testing-mail-code-in-spring-boot-application.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/361808.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CSS基础语法(三) CSS的6种特性

样式表常用写法及特性&#xff08;组合、继承、关联性、权值性、层叠性、重要性&#xff09; 1.样式的组合&#xff1a;把具有相同声明定义的选择符组合在一起&#xff0c;并用逗号隔开。&#xff0d;例如&#xff1a;段落元素p、单元格元素td和类c1可以使用相同样式&#xff…

卷积,DFT,FFT,图像FFT,FIR 和 IIR 的物理意义

卷积&#xff1a; 冲击信号会对线性系统产生冲击响应。 冲击信号可分解为平移度和幅度。其对线性系统的冲击响应可以分解为点点间的经平移和缩放的各个冲击响应的累加&#xff0c;通过卷积的表达式表示。 所谓的冲击响应&#xff0c;就是线性系统对任何输入信号的响应&#xff…

洛谷P2822 组合数问题

分析&#xff1a; 首先预处理出来&#xff0c;杨辉三角二维前缀和 代码&#xff1a; #include<cstdio> using namespace std; long long f[2005][2005],sum[2005][2005]; int main() {long long T,k;scanf("%lld%lld",&T,&k);for(long long i0;i<20…

es6笔记

es6对象浅复制&#xff1a; 字符串大小比较&#xff1a; 如果是汉字&#xff1a;a.charCodeAt() > b.charCodeAt() //使用carCodeAt将器转为asci码&#xff0c;在进行比较 如果是非汉字的字符串&#xff1a;直接比较或者使用上面的转码比较都可以。 如果是日期比较&#xff…

毕业设计上线啦!----跳蚤部落与基于Comet的WebIM系统开发

我不清楚把我的毕业设计的东西放上来之后&#xff0c;毕业论文答辩的时候会不会说我是在网上抄袭的&#xff0c;不过我还是果断的发上来与大家分享了&#xff01;&#xff01;呵呵&#xff0c;请大家支持&#xff01;高手就绕道吧&#xff01; 现在已经放到公网上&#xff0c;并…

poj2032Square Carpets(IDA* + dancing links)

题目请戳这里 题目大意:给一个H行W列的01矩阵,求最少用多少个正方形框住所有的1. 题目分析:又是一个红果果的重复覆盖模型.DLX搞之! 枚举矩阵所有的子正方形,全1的话建图.判断全1的时候,用了一个递推,dp[i][j][w][h]表示左上角(i,j)的位置开始长h宽w的矩形中1的个数,这样后面可…

使用Spring Security保护REST服务

总览 最近&#xff0c;我正在一个使用REST服务层与客户端应用程序&#xff08;GWT应用程序&#xff09;进行通信的项目中。 因此&#xff0c;我花了很多时间来弄清楚如何使用Spring Security保护REST服务。 本文介绍了我找到的解决方案&#xff0c;并已实现。 我希望此解决方案…

http请求post,返回excel文件,并接收

1.post的方法里要加responseType: arraybuffer参数&#xff0c;不然下载的excel会乱码 2.使用{type: "application/vnd.ms-excel"}的写法&#xff0c;可以保存为xls格式的excel文件&#xff08;兼容老版本&#xff09;。而使用“application/vnd.openxmlformats-off…

linux图形开发工具

请见:http://hi.baidu.com/jjzhang166/blog/item/b8dfb6ecd5fc6e2d62d09f9e.html 转载于:https://www.cnblogs.com/vilyLei/archive/2011/12/12/2284869.html

具有Overlord的WildFly 8.1中的API管理

昨天&#xff0c;我简要介绍了霸王项目家族。 今天该试驾了。 API管理子项目两天前发布了1.0.0.Alpha1&#xff0c;并根据18个月的路线图介绍了第一组功能。 APIMan到底是什么&#xff1f; 它是一个API管理系统&#xff0c;可以嵌入现有框架或应用程序中&#xff0c;甚至可以作…

设计模式学习笔记-代理模式

1. 概述 为其它对象提供一种代理以控制对这个对象的访问。 解决的问题&#xff1a;如果直接访问对象比较困难&#xff0c;或直接访问会给使用者或系统带来一系列问题。这样对于客户端&#xff08;调用者&#xff09;来说&#xff0c;就不需要直接与真实对象进行交互&#xff0c…

Tomcat配置自签名https

从JDK中找到keytool.exe&#xff0c;随便复制到一个方便的目录&#xff0c;在命令行中进入这个目录。 第一步&#xff1a;为服务器生成证书 tomcat.keystore&#xff0c;名字就是域名&#xff0c;其他的看着写。 keytool -genkey -v -alias tomcat -keyalg RSA -validity 3650…

MFC学习之路之多媒体 --(1) DirectShow

可以说整个Windows的多媒体编程都是以DirectShow为基础&#xff0c;那好&#xff0c;来吧&#xff0c;我们直接看DirectShow的一段基础代码。 bool Mp3::Load(LPCWSTR szFile) {Cleanup();ready false;if (SUCCEEDED(CoCreateInstance( CLSID_FilterGraph,NULL,CLSCTX_INPROC_…

使用反射处理Java批注

在上一篇有关Java注释的文章中&#xff0c;我概述了一个最近的用例&#xff0c;并为您提供了一些自定义注释的示例以及如何使用它们。 在本文中&#xff0c;我将更进一步&#xff0c;并为您提供一些自定义注释的示例&#xff0c;以及如何使用Java Reflection API处理这些自定义…

Excel 2007 Open XML文件结构(2)

Excel 2007 Open XML文件结构&#xff08;2&#xff09; 在以上文件中&#xff0c;根据<sheet>元素中r:id属性的值可得到工作表数据的XML文件。例如&#xff0c;在workbook.xml文件中名为工作表1的工作表的r:id属性为rld1&#xff0c;在以上文件中根据ID找到以下代码&…

Vue.js最佳实践

Vue.js最佳实践 第一招&#xff1a;化繁为简的Watchers 场景还原&#xff1a; created(){this.fetchPostList() },watch: {searchInputValue(){this.fetchPostList()} } 组件创建的时候我们获取一次列表&#xff0c;同时监听input框&#xff0c;每当发生变化的时候重新获取一…

Api demo源码学习(8)--App/Activity/QuickContactsDemo --获取系统联系人信息

本节通过Content Provider机制获取系统中的联系人信息&#xff0c;注意这个Anctivity直接继承的是ListActivity&#xff0c;所以不再需要setContentView函数来加载布局文件了&#xff08;我自己新建一个项目来跑这个anctivity时在这里卡了半天&#xff09;。 在AndroidManifest…

游戏大厅 从基础开始(6)--绕回来细说聊天室(中)之女仆编年史1

上一篇我们大致的了解了几种聊天室的行为模式 最简单明了的推模式 几乎不需要任何多余的语言来描述它的实现 这一篇我们看看如何实现拉模式更有效。 本图清晰的表现了"拉"模式聊天室的行为。 并发多用户向数据池写数据 并发多用户从数据池读书据 数据最好以时间为…

开发自上而下的Web服务项目

这是从Alessio Soldano编辑的Advanced JAX-WS Web Services手册中摘录的示例章节。 第一章介绍了自底向上创建Web服务端点的方法。 它允许非常快地将现有bean作为Web Service端点公开&#xff1a;在大多数情况下&#xff0c;将类转换为端点只需在代码中添加少量注释即可。 但…

React中ref的使用方法

React中ref的使用方法 在react典型的数据流中&#xff0c; props传递是父子组件交互的唯一方式&#xff1b;通过传递一个新的 props值来使子组件重新 re-render,从而达到父子组件通信。当然&#xff0c;就像react官网所描述的一样&#xff0c;在react典型的数据量之外&#xff…