├── .gitignore
├── README.md
├── pom.xml
└── src
├── main
├── java
│ └── com
│ │ └── mvpjava
│ │ ├── Main.java
│ │ ├── mongo
│ │ ├── LogController.java
│ │ ├── LogRecord.java
│ │ ├── LogRepository.java
│ │ └── MongoService.java
│ │ └── mongoconfig
│ │ ├── MongoConfigProfiles.java
│ │ ├── MongoProperties.java
│ │ └── SystemProfileValueSource2.java
└── resources
│ ├── application-it-embedded.properties
│ ├── application-it.properties
│ ├── application-prod.properties
│ └── application.properties
└── test
└── java
├── com
└── mvpjava
│ └── it
│ └── mongo
│ ├── embeddedMongo
│ ├── MongoSliceIT.java
│ ├── MongoSliceWithServiceIT.java
│ └── MongoTomcatIT.java
│ └── realMongo
│ └── RealMongoEmbeddTomcatIT.java
└── unit
└── UselessUnitTest.java
/.gitignore:
--------------------------------------------------------------------------------
1 | *.class
2 |
3 | # Mobile Tools for Java (J2ME)
4 | .mtj.tmp/
5 |
6 | # Package Files #
7 | *.jar
8 | *.war
9 | *.ear
10 |
11 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
12 | hs_err_pid*
13 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # springboot-IntegrationTests-Tutorial
2 |
3 | Covers how to select and execute different groups/sub-sets of Integration Tests by taking a layered approach.
4 |
5 | The Spring Boot testing tutorial covers how to define and activate different Spring Profiles via annotaions and
6 | property files in order to switch between executing an embedded mongoDB integration test or a real mongoDB database.
7 |
8 | The Project uses Spring Boot Testing 1.5 which allows you to test a slice of you application via the use the @DataMongoTest annotation and also how to perform more broad based integration testing via the use of the @SpringBootTest annotation.
9 |
10 | You can also follow along with my YouTube video Tutorial
11 | https://youtu.be/VeFr1CRFdC4
12 |
13 | You can follow the Blog Post which goes along with this Project on mvpjava.com
14 | http://mvpjava.com/spring-boot-integration-testing/
15 |
16 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | com.example
7 | springbootIntegrationTestsTutorial
8 | 0.0.1-SNAPSHOT
9 | jar
10 |
11 | springbootIntegrationTestsTutorial
12 | Spring Boot Profiles, Environment Tutorial
13 |
14 |
15 | org.springframework.boot
16 | spring-boot-starter-parent
17 | 1.5.2.RELEASE
18 |
19 |
20 |
21 |
22 | UTF-8
23 | 1.8
24 |
25 |
26 |
27 |
28 | org.springframework.boot
29 | spring-boot-starter-test
30 | test
31 |
32 |
33 |
34 | org.springframework.boot
35 | spring-boot-starter-data-mongodb
36 |
37 |
38 |
39 | org.springframework.boot
40 | spring-boot-starter-web
41 |
42 |
43 | de.flapdoodle.embed
44 | de.flapdoodle.embed.mongo
45 | test
46 |
47 |
48 | org.springframework
49 | spring-core
50 | jar
51 |
52 |
53 | org.springframework
54 | spring-test
55 | jar
56 |
57 |
58 |
59 |
60 |
61 |
62 | org.springframework.boot
63 | spring-boot-maven-plugin
64 |
65 |
66 | it-embedded
67 |
68 |
69 |
70 |
71 |
72 | org.apache.maven.plugins
73 | maven-failsafe-plugin
74 |
75 |
76 |
77 | integration-test
78 | verify
79 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/src/main/java/com/mvpjava/Main.java:
--------------------------------------------------------------------------------
1 | package com.mvpjava;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class Main {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(Main.class);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/mvpjava/mongo/LogController.java:
--------------------------------------------------------------------------------
1 | /*
2 | * To change this license header, choose License Headers in Project Properties.
3 | * To change this template file, choose Tools | Templates
4 | * and open the template in the editor.
5 | */
6 | package com.mvpjava.mongo;
7 |
8 | import org.springframework.web.bind.annotation.RequestBody;
9 | import org.springframework.web.bind.annotation.RequestMapping;
10 | import org.springframework.web.bind.annotation.RequestMethod;
11 | import org.springframework.web.bind.annotation.ResponseBody;
12 | import org.springframework.web.bind.annotation.RestController;
13 |
14 | @RestController
15 | public class LogController {
16 |
17 | private final MongoService mongoService;
18 |
19 | public LogController(MongoService mongoService) {
20 | this.mongoService = mongoService;
21 | }
22 |
23 | @RequestMapping(value = "/log", method = RequestMethod.POST)
24 | @ResponseBody
25 | public LogRecord log(@RequestBody LogRecord logRecord) {
26 | LogRecord log = mongoService.log(logRecord);
27 | return log;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/com/mvpjava/mongo/LogRecord.java:
--------------------------------------------------------------------------------
1 | package com.mvpjava.mongo;
2 |
3 | import java.util.Date;
4 | import java.util.Objects;
5 | import org.springframework.data.annotation.Id;
6 | import org.springframework.data.mongodb.core.mapping.Document;
7 |
8 | /**
9 | * Used in Mapping the Log record from Java Object to Mongo DBObject and back.
10 | */
11 | @Document
12 | public class LogRecord {
13 | @Id private String id;
14 | private String level;
15 | private Date timestamp;
16 | private String message;
17 |
18 | public LogRecord() {
19 | }
20 |
21 | public LogRecord(String level, String message) {
22 | this.level = level;
23 | this.message = message;
24 | setTimestamp(new Date());
25 | }
26 |
27 |
28 | public String getId() {
29 | return id;
30 | }
31 |
32 | public void setId(String mongoId) {
33 | this.id = mongoId;
34 | }
35 |
36 | public String getLevel() {
37 | return level;
38 | }
39 |
40 | public void setLevel(String level) {
41 | this.level = level;
42 | }
43 |
44 | public String getMessage() {
45 | return message;
46 | }
47 |
48 | public void setMessage(String message) {
49 | this.message = message;
50 | }
51 |
52 | public Date getTimestamp() {
53 | return timestamp;
54 | }
55 |
56 | public void setTimestamp(Date timestamp) {
57 | this.timestamp = timestamp;
58 | }
59 |
60 | @Override
61 | public int hashCode() {
62 | int hash = 7;
63 | hash = 23 * hash + Objects.hashCode(this.level);
64 | hash = 23 * hash + Objects.hashCode(this.timestamp);
65 | hash = 23 * hash + Objects.hashCode(this.message);
66 | return hash;
67 | }
68 |
69 | @Override
70 | public boolean equals(Object obj) {
71 | if (this == obj) {
72 | return true;
73 | }
74 | if (obj == null) {
75 | return false;
76 | }
77 | if (getClass() != obj.getClass()) {
78 | return false;
79 | }
80 | final LogRecord other = (LogRecord) obj;
81 | if (!Objects.equals(this.level, other.level)) {
82 | return false;
83 | }
84 | if (!Objects.equals(this.message, other.message)) {
85 | return false;
86 | }
87 | if (!Objects.equals(this.timestamp, other.timestamp)) {
88 | return false;
89 | }
90 | return true;
91 | }
92 |
93 | @Override
94 | public String toString() {
95 | return "LogRecord{" + "id=" + id + ", level=" + level + ", timestamp=" + timestamp + ", message=" + message + '}';
96 | }
97 |
98 | }
99 |
--------------------------------------------------------------------------------
/src/main/java/com/mvpjava/mongo/LogRepository.java:
--------------------------------------------------------------------------------
1 | package com.mvpjava.mongo;
2 |
3 | import org.springframework.data.mongodb.repository.MongoRepository;
4 |
5 | public interface LogRepository extends MongoRepository{
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/java/com/mvpjava/mongo/MongoService.java:
--------------------------------------------------------------------------------
1 | package com.mvpjava.mongo;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.dao.DataAccessException;
5 | import org.springframework.data.mongodb.core.MongoTemplate;
6 | import org.springframework.stereotype.Service;
7 |
8 | @Service
9 | public class MongoService {
10 |
11 | private final MongoTemplate mongoTemplate;
12 |
13 | private final String logsCollectionName = "logs";
14 |
15 | @Autowired
16 | public MongoService(MongoTemplate mongoTemplate) {
17 | this.mongoTemplate = mongoTemplate;
18 | }
19 |
20 | public LogRecord log(LogRecord logRecord) throws DataAccessException {
21 | mongoTemplate.save(logRecord, logsCollectionName);
22 | return findLogMessageById(logRecord.getId());
23 | }
24 |
25 | public LogRecord findLogMessageById(String id) {
26 | return mongoTemplate.findById(
27 | id, LogRecord.class, logsCollectionName);
28 | }
29 |
30 | public void removeLogCollection() {
31 | mongoTemplate.dropCollection(logsCollectionName);
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/com/mvpjava/mongoconfig/MongoConfigProfiles.java:
--------------------------------------------------------------------------------
1 | package com.mvpjava.mongoconfig;
2 |
3 | import com.mongodb.MongoClient;
4 | import org.springframework.context.annotation.Bean;
5 | import org.springframework.context.annotation.Configuration;
6 | import org.springframework.context.annotation.Profile;
7 | import org.springframework.data.mongodb.MongoDbFactory;
8 | import org.springframework.data.mongodb.core.MongoTemplate;
9 | import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
10 |
11 | @Configuration
12 | @Profile("!it-embedded") //or else problems when using @EnableAutoConfiguration in Integration ests
13 | public class MongoConfigProfiles {
14 |
15 | private final MongoProperties mongoProperties;
16 |
17 | public MongoConfigProfiles(MongoProperties mongoProperties) {
18 | this.mongoProperties = mongoProperties;
19 | }
20 |
21 | @Bean
22 | public MongoDbFactory mongoDbFactory() throws Exception {
23 | MongoClient mongoClient = new MongoClient(mongoProperties.getHost(), mongoProperties.getPort());
24 | return new SimpleMongoDbFactory(mongoClient, mongoProperties.getDatabase());
25 | }
26 |
27 | @Bean
28 | public MongoTemplate mongoTemplate() throws Exception {
29 | MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory());
30 | return mongoTemplate;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/java/com/mvpjava/mongoconfig/MongoProperties.java:
--------------------------------------------------------------------------------
1 | package com.mvpjava.mongoconfig;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.core.env.Environment;
5 | import org.springframework.stereotype.Component;
6 |
7 | @Component
8 | public class MongoProperties {
9 |
10 | private final Environment environment;
11 |
12 | @Autowired
13 | public MongoProperties(Environment environment) {
14 | this.environment = environment;
15 | }
16 |
17 | public String getDatabase() {
18 | return environment.getProperty("mongodb.database");
19 | }
20 |
21 | public String getHost() {
22 | return environment.getProperty("mongodb.host");
23 | }
24 |
25 | public int getPort() {
26 | return environment.getProperty("mongodb.port", Integer.class);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/com/mvpjava/mongoconfig/SystemProfileValueSource2.java:
--------------------------------------------------------------------------------
1 | package com.mvpjava.mongoconfig;
2 |
3 | import java.util.Objects;
4 | import org.springframework.stereotype.Component;
5 | import org.springframework.test.annotation.ProfileValueSource;
6 | import org.springframework.util.Assert;
7 | import org.springframework.util.StringUtils;
8 |
9 | @Component
10 | public class SystemProfileValueSource2 implements ProfileValueSource {
11 |
12 | @Override
13 | public String get(String key) {
14 | Assert.hasText(key, "'key' must not be empty");
15 | String springProfiles = System.getProperty(key);
16 | if (Objects.isNull(key) || StringUtils.isEmpty(springProfiles)) {
17 | return "it-embedded";
18 | }
19 |
20 | return System.getProperty(key);
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/resources/application-it-embedded.properties:
--------------------------------------------------------------------------------
1 | # MONGODB (MongoProperties for embedded)
2 | spring.data.mongodb.host=127.0.0.1
3 | spring.data.mongodb.port=0
4 | spring.data.mongodb.database=embeddedDB
--------------------------------------------------------------------------------
/src/main/resources/application-it.properties:
--------------------------------------------------------------------------------
1 | ## MONGODB (MongoProperties)
2 | spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration
3 | mongodb.database=testint
4 | mongodb.host=localhost
5 | mongodb.port=27017
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/src/main/resources/application-prod.properties:
--------------------------------------------------------------------------------
1 | ## MONGODB (MongoProperties)
2 | spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration
3 | mongodb.database=clients
4 | mongodb.host=172.0.3.1
5 | mongodb.port=27018
6 | #mongodb.password=mvpjavasecret
7 | #mongodb.username=mvpjava
--------------------------------------------------------------------------------
/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | # If No active profile set, then use this one as the active one
2 | spring.profiles.active=it-embedded
--------------------------------------------------------------------------------
/src/test/java/com/mvpjava/it/mongo/embeddedMongo/MongoSliceIT.java:
--------------------------------------------------------------------------------
1 | package com.mvpjava.it.mongo.embeddedMongo;
2 |
3 | import static org.junit.Assert.*;
4 | import static org.springframework.core.env.AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME;
5 |
6 | import com.mongodb.DBCollection;
7 | import com.mvpjava.mongo.LogRecord;
8 | import com.mvpjava.mongo.LogRepository;
9 | import com.mvpjava.mongoconfig.SystemProfileValueSource2;
10 | import org.junit.After;
11 | import org.junit.Before;
12 | import org.junit.Test;
13 | import org.junit.runner.RunWith;
14 | import org.springframework.beans.factory.annotation.Autowired;
15 | import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
16 | import org.springframework.data.mongodb.core.MongoTemplate;
17 | import org.springframework.data.mongodb.core.query.Criteria;
18 | import org.springframework.data.mongodb.core.query.Query;
19 | import org.springframework.test.annotation.IfProfileValue;
20 | import org.springframework.test.annotation.ProfileValueSourceConfiguration;
21 | import org.springframework.test.context.junit4.SpringRunner;
22 |
23 | @ProfileValueSourceConfiguration(value = SystemProfileValueSource2.class)
24 | @IfProfileValue(name = ACTIVE_PROFILES_PROPERTY_NAME, value = "it-embedded") //"spring.profiles.active"
25 | @RunWith(SpringRunner.class)
26 | @DataMongoTest
27 | public class MongoSliceIT {
28 |
29 | String collectionName;
30 | LogRecord logRecToInsert;
31 |
32 | @Autowired
33 | private MongoTemplate mongoTemplate;
34 |
35 | @Autowired
36 | private LogRepository logRepository;
37 |
38 | @Before
39 | public void before() {
40 | collectionName = "logs";
41 | logRecToInsert = new LogRecord("INFO", "Test Info Log messge");
42 | }
43 |
44 | @After
45 | public void after() {
46 | mongoTemplate.dropCollection(collectionName);
47 | }
48 |
49 | @Test
50 | public void checkMongoTemplate() {
51 | assertNotNull(mongoTemplate);
52 | DBCollection createdCollection = mongoTemplate.createCollection(collectionName);
53 | assertTrue(mongoTemplate.collectionExists(collectionName));
54 | }
55 |
56 | @Test
57 | public void checkDocumentAndQuery() {
58 | mongoTemplate.save(logRecToInsert, collectionName);
59 | Query query = new Query(new Criteria()
60 | .andOperator(Criteria.where("level").regex(logRecToInsert.getLevel()),
61 | Criteria.where("message").regex(logRecToInsert.getMessage())));
62 |
63 | LogRecord retrievedLogRecord = mongoTemplate.findOne(query, LogRecord.class, collectionName);
64 | assertNotNull(retrievedLogRecord);
65 | }
66 |
67 | @Test
68 | public void checkLogRepository() {
69 | assertNotNull(logRepository);
70 | LogRecord savedLogRecord = logRepository.save(logRecToInsert);
71 | assertNotNull(logRepository.findOne(savedLogRecord.getId()));
72 | }
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/src/test/java/com/mvpjava/it/mongo/embeddedMongo/MongoSliceWithServiceIT.java:
--------------------------------------------------------------------------------
1 | package com.mvpjava.it.mongo.embeddedMongo;
2 |
3 | import static org.junit.Assert.*;
4 | import static org.springframework.core.env.AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME;
5 |
6 | import com.mvpjava.mongo.LogRecord;
7 | import com.mvpjava.mongo.MongoService;
8 | import com.mvpjava.mongoconfig.SystemProfileValueSource2;
9 | import org.junit.Test;
10 | import org.junit.runner.RunWith;
11 | import org.springframework.beans.factory.annotation.Autowired;
12 | import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
13 | import org.springframework.context.annotation.ComponentScan.Filter;
14 | import org.springframework.stereotype.Service;
15 | import org.springframework.test.annotation.IfProfileValue;
16 | import org.springframework.test.annotation.ProfileValueSourceConfiguration;
17 | import org.springframework.test.context.junit4.SpringRunner;
18 |
19 | @ProfileValueSourceConfiguration(value = SystemProfileValueSource2.class)
20 | @IfProfileValue(name = ACTIVE_PROFILES_PROPERTY_NAME, value = "it-embedded") //"spring.profiles.active"
21 | @RunWith(SpringRunner.class)
22 | @DataMongoTest(includeFilters = @Filter(Service.class))
23 | public class MongoSliceWithServiceIT {
24 |
25 | @Autowired
26 | private MongoService mongoService;
27 |
28 | @Test
29 | public void ensureLoggingWorks() {
30 | LogRecord logRecord = new LogRecord("INFO", "This is a test");
31 | LogRecord logWithPK = mongoService.log(logRecord);
32 | assertNotNull(logWithPK.getId());
33 | assertEquals(logRecord.getMessage(), logWithPK.getMessage());
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/test/java/com/mvpjava/it/mongo/embeddedMongo/MongoTomcatIT.java:
--------------------------------------------------------------------------------
1 | package com.mvpjava.it.mongo.embeddedMongo;
2 |
3 | import static org.junit.Assert.*;
4 | import static org.springframework.boot.test.context.SpringBootTest.*;
5 | import static org.springframework.core.env.AbstractEnvironment.*;
6 |
7 | import com.mvpjava.mongo.LogRecord;
8 | import com.mvpjava.mongoconfig.SystemProfileValueSource2;
9 | import org.junit.Test;
10 | import org.junit.runner.RunWith;
11 | import org.springframework.beans.factory.annotation.Autowired;
12 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
13 | import org.springframework.boot.test.context.SpringBootTest;
14 | import org.springframework.boot.test.web.client.TestRestTemplate;
15 | import org.springframework.http.ResponseEntity;
16 | import org.springframework.test.annotation.IfProfileValue;
17 | import org.springframework.test.annotation.ProfileValueSourceConfiguration;
18 | import org.springframework.test.context.junit4.SpringRunner;
19 |
20 | @ProfileValueSourceConfiguration(value = SystemProfileValueSource2.class)
21 | @IfProfileValue(name = ACTIVE_PROFILES_PROPERTY_NAME, value = "it-embedded")
22 | @RunWith(SpringRunner.class)
23 | @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
24 | @EnableAutoConfiguration //mongoDB
25 | public class MongoTomcatIT {
26 |
27 | @Autowired
28 | private TestRestTemplate restTemplate;
29 |
30 | @Test
31 | public void ensureLoggingWorks() {
32 | LogRecord logRecord = new LogRecord("INFO", "This is a test");
33 | ResponseEntity responseEntity = restTemplate.postForEntity(
34 | "/log", logRecord, LogRecord.class);
35 | LogRecord logRecordReturned = responseEntity.getBody();
36 |
37 | assertNotNull("Should have an PK", logRecordReturned.getId());
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/test/java/com/mvpjava/it/mongo/realMongo/RealMongoEmbeddTomcatIT.java:
--------------------------------------------------------------------------------
1 | package com.mvpjava.it.mongo.realMongo;
2 |
3 | import static org.junit.Assert.*;
4 | import static org.springframework.boot.test.context.SpringBootTest.*;
5 | import static org.springframework.core.env.AbstractEnvironment.*;
6 |
7 | import com.mvpjava.mongo.LogRecord;
8 | import com.mvpjava.mongoconfig.SystemProfileValueSource2;
9 | import org.junit.Test;
10 | import org.junit.runner.RunWith;
11 | import org.springframework.beans.factory.annotation.Autowired;
12 | import org.springframework.boot.test.context.SpringBootTest;
13 | import org.springframework.boot.test.web.client.TestRestTemplate;
14 | import org.springframework.http.ResponseEntity;
15 | import org.springframework.test.annotation.IfProfileValue;
16 | import org.springframework.test.annotation.ProfileValueSourceConfiguration;
17 | import org.springframework.test.context.junit4.SpringRunner;
18 |
19 | @ProfileValueSourceConfiguration(value = SystemProfileValueSource2.class)
20 | @IfProfileValue(name = ACTIVE_PROFILES_PROPERTY_NAME, value = "it")
21 | @RunWith(SpringRunner.class)
22 | @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
23 | public class RealMongoEmbeddTomcatIT {
24 | @Autowired
25 | private TestRestTemplate restTemplate;
26 |
27 | @Test
28 | public void ensureLoggingWorks() {
29 | LogRecord logRecord = new LogRecord("INFO", "This is a test on real monngoDB");
30 | ResponseEntity responseEntity = restTemplate.postForEntity(
31 | "/log", logRecord, LogRecord.class);
32 | LogRecord logRecordReturned = responseEntity.getBody();
33 |
34 | assertNotNull("Should have an PK", logRecordReturned.getId());
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/test/java/unit/UselessUnitTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * To change this license header, choose License Headers in Project Properties.
3 | * To change this template file, choose Tools | Templates
4 | * and open the template in the editor.
5 | */
6 | package unit;
7 |
8 | import org.junit.Test;
9 | import static org.junit.Assert.assertTrue;
10 |
11 | public class UselessUnitTest {
12 |
13 | @Test
14 | public void uselessUnitTest() {
15 | assertTrue(true);
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------