Spring Boot : Integration tests with environment variables
If you want to read about setting up an EmailService which reads the credentials from environment variables please refer to my article on:

If you want to read about setting up an EmailService which reads the credentials from environment variables please refer to my article on:
Spring Boot : Configuring environment variables
Spring Boot : Using and overwriting environment variables
In a spring boot application, at some point or the other you will want to externalise your configurations for obvious…medium.com
Writing integration tests for an EmailService
Now that our code works, we want to write an integration test for EmailService.
It can be done using GreenMail which creates a SMTP server for us and receives all the emails we send through our test.
You can read about about GreenMail here:
GreenMail
GreenMail is an open source, intuitive and easy-to-use test suite of email servers for testing purposes. Typical use…www.icegreen.com
So let’s see how our EmailServiceTest class looks like:
@RunWith(SpringRunner.class)@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)@ActiveProfiles("test")public class EmailServiceTest { @Autowired private EmailService emailService; private GreenMail greenMail;
@Before public void setup(){ ServerSetup serverSetup = new ServerSetup(3025,"localhost","smtp"); greenMail = new GreenMail(serverSetup); greenMail.start(); }
@After public void stop(){ greenMail.stop(); }
@Test public void shouldSendAnEmail() { GreenMailUser user = greenMail.setUser("user@localhost.com", "password"); emailService.send(new EmailTemplate("Learning something interesting", "Looks great!"), "coolDeveloper@interleap.co"); assertTrue(greenMail.waitForIncomingEmail(1000, 1)); }}
And our application-test.properties looks like this:
SMTP_SERVER_PORT=3025SMTP_SERVER_HOST=localhostSMTP_USER_NAME=user@localhost.comSMTP_USER_PASSWORD=password
But the above test will fail saying invalid credentials as @Value
will pick the environment variables with real SMTP server credentials and not our set credentails for GreenMail.
co.interleap.controllers.EmailServiceTest > shouldSendAnEmail FAILED
java.lang.AssertionError at EmailServiceTest.java:52

One way to get around this is to make sure that the jar is not provided with these environment variables, which sounds like a little unnecessary hassle at-least in this case.
What is the best way to get around this problem then?
Spring Boot comes to rescue us here with it’s annotations.
We can use an annotation called @TestPropertySource
to make our SMTP server use the right credentials.
TestPropertySource
@TestPropertySource
is a class-level annotation that is used to configure the locations()
of properties files and inlined properties()
to be added to the Environment
's set of PropertySources
for an ApplicationContext
for integration tests.
Test property sources have higher precedence than those loaded from the operating system’s environment or Java system properties as well as property sources added by the application declaratively via
@PropertySource
or programmatically (e.g., via anApplicationContextInitializer
or some other means).
Thus, test property sources can be used to selectively override properties defined in system and application property sources. Furthermore, inlined
properties()
have higher precedence than properties loaded from resourcelocations()
.
What this means is any property that is declared using@TestPropertySource
will overwrite the properties picked externally. In our case, environment variables having our SMTP_SERVER credentials.
Properties
public abstract String[] properties
Inlined properties in the form of key-value pairs that should be added to the Spring Environment
before the ApplicationContext
is loaded for the test. All key-value pairs will be added to the enclosing Environment
as a single test PropertySource
with the highest precedence.
So in our case all we need to ensure that our test runs correctly is annotate the test class with this annotation and declare the SMTP configuration inside :
@RunWith(SpringRunner.class)@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)@TestPropertySource(properties = {"SMTP_SERVER_PORT=3025", "SMTP_SERVER_HOST=localhost", "SMTP_USER_NAME=user@localhost.com", "SMTP_USER_PASSWORD=password"})@ActiveProfiles("test")class EmailServiceTest {/*Your tests*/}
If you have multiple properties you want to overwrite, you can just create another or use any existing application.properties file and mention it in locations attribute of @TestPropertySource
:
Once we are done with these changes, we can see our test passes even when it has access to the environment variables.

Our code will look like this once we use application-test.properties in locations attribute:
EmailServiceTest.java
@RunWith(SpringRunner.class)@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)@TestPropertySource(locations = {"classpath:application-test.properties"})@ActiveProfiles("test")class EmailServiceTest {/*Your tests*/}
application-test.properties
SMTP_SERVER_PORT=3025SMTP_SERVER_HOST=localhostSMTP_USER_NAME=user@localhost.comSMTP_USER_PASSWORD=password
Our Final Code
@RunWith(SpringRunner.class)@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)@TestPropertySource(locations = {"classpath:application-test.properties"},properties = "management.port=0")@ActiveProfiles("test")public class EmailServiceTest { @Autowired private EmailService emailService; private GreenMail greenMail;
@Before public void setup(){ ServerSetup serverSetup = new ServerSetup(3025,"localhost","smtp"); greenMail = new GreenMail(serverSetup); greenMail.start(); }
@After public void stop(){ greenMail.stop(); }
@Test public void shouldSendAnEmail() { GreenMailUser user = greenMail.setUser("user@localhost.com", "password"); emailService.send(new EmailTemplate("Learning something interesting", "Looks great!"), "coolDeveloper@interleap.co"); assertTrue(greenMail.waitForIncomingEmail(1000, 1)); }}
application-test.properties
SMTP_SERVER_PORT=3025SMTP_SERVER_HOST=localhostSMTP_USER_NAME=user@localhost.comSMTP_USER_PASSWORD=password
And now the tests will work as expected.

You can find the EmailService.java and application-test.properties file here:
kooskoos20/GreenMailTest
You can't perform that action at this time. You signed in with another tab or window. You signed out in another tab or…github.com
Hope you learned something interesting.
Happy Coding!!!