在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;

    @Bean
    public 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;

    @Autowired
    MailSubmissionController(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;

    @Autowired
    private WebApplicationContext wac;
    private MockMvc mockMvc;


    @Before
    public void setUp() throws Exception {
        wiser = new Wiser();
        wiser.start();
        mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
    }

    @After
    public void tearDown() throws Exception {
        wiser.stop();
    }

    @Test
    public void send() throws Exception {
        // act
        mockMvc.perform(get("/mail"))
                .andExpect(status().isCreated());
        // assert
        assertReceivedMessage(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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值