测试在Spring发送电子邮件

时间:2016-07-05 19:28:50

标签: spring spring-boot automated-tests integration-testing

我想在春天测试我的服务,它应该发送电子邮件。 我尝试使用org.subethamail:subethasmtp

为了实现我的目标,我创建了服务MySender,我发送了电子邮件:

@Autowired
private MailSender mailSender;

//...
    SimpleMailMessage message = new SimpleMailMessage();
    message.setTo("example@example.com");
    message.setSubject("Subject");
    message.setText("Text");
    mailSender.send(message);
// ...

为了测试这段代码,我创建了测试application.properties(在测试范围内):

spring.mail.host=127.0.0.1
spring.mail.port=${random.int[4000,6000]}

测试配置类,它应启动Wiser SMTP服务器并使其在测试中可重用:

@Configuration
public class TestConfiguration {

    @Autowired
    private Wiser wiser;

    @Value("${spring.mail.host}")
    String smtpHost;

    @Value("${spring.mail.port}")
    int smtpPort;

    @Bean
    public Wiser provideWiser() {
        // provide wiser for verification in tests
        Wiser wiser = new Wiser();
        return wiser;
    }

    @PostConstruct
    public void initializeMailServer() {
        // start server
        wiser.setHostname(smtpHost);
        wiser.setPort(smtpPort);
        wiser.start();
    }

    @PreDestroy
    public void shutdownMailServer() {
        // stop server
        wiser.stop();
    }

}

预期结果是应用程序使用Wiser smtp服务器发送电子邮件并验证已发送邮件的数量。

但是当我运行服务应用程序时抛出MailSendException(Couldn't connect to host, port: 127.0.0.1, 4688; timeout -1;)。 但是当我添加断点并尝试使用telnet smtp服务器连接时,允许连接并且不要抛出Connection refused

你知道为什么我不能测试发送邮件吗?

github上提供完整代码预览: https://github.com/karolrynio/demo-mail

2 个答案:

答案 0 :(得分:0)

您可以在应用程序属性中添加

.so

将代码更改为具有这两个额外的值

mail.smtp.auth=false
mail.smtp.starttls.enable=false

并将这些选项放在initializeMailServer

 @Value("${mail.smtp.auth}")
 private boolean auth;

 @Value("${mail.smtp.starttls.enable}")
 private boolean starttls;

让我知道这是否适合您

答案 1 :(得分:0)

我遇到了同样的问题。如果在测试Spring配置中结合Maven测试分支使用spring.mail.port的某个常量端口号,则会导致测试在启动Wiser时随机发生端口冲突失败。 正如评论中所述,使用random.int并不会有帮助 - 每次引用时都会返回不同的值,以及它的预期行为(请参阅此issue)。 因此,我们需要一种不同的方法来使用随机值初始化spring.mail.port,因此它在测试执行中将保持不变。这是一种方法(感谢您的建议here):

首先,我们可能根本不在测试属性文件中设置spring.mail.port。我们会在TestPropertySource初始化它。我们需要这样的课程:

public class RandomPortInitailizer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        int randomPort = SocketUtils.findAvailableTcpPort();
        TestPropertySourceUtils.addInlinedPropertiesToEnvironment(applicationContext,
                "spring.mail.port=" + randomPort);
    }
}

现在我们可以通过这种方式运行我们的测试(与OP中的测试结果差别不大):

@RunWith(SpringRunner.class)
@ContextConfiguration(initializers = RandomPortInitailizer.class)
public class WhenEmailingSomeStuff {
    @Value("${spring.mail.host}")
    String smtpHost;
    @Value("${spring.mail.port}")
    int smtpPort;

    @Before
    public void startEmailServer() {
        wiser = new Wiser();
        wiser.setPort(smtpPort);
        wiser.setHostname(smtpHost);
        wiser.start();
    }

    @After
    public void stopEmailServer() {
        wiser.stop();
    }

    @Test
    public void testYourJavaMailSenderHere() {
        //
    }
}