7

I have been trying to follow the instructions in the link below to try to add an automatically configured Embedded MongoDB Instance for Cucumber Integration testing. This is currently not working, since the I keep getting a null MongoTemplate. I thought that @DataMongoTest would automatically configure "@Autowired private MongoTemplate mongoTemplate;" Is this not the case? Below is my code:

mongoTemplate.save(doc, collection); throws a nullpointer exception.

@SpringBootTest(classes = AppCommentApiApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@DataMongoTest
public abstract class SpringIntegrationTest {

    @Value("${local.server.port}")
    public int port;

    @Autowired
    private MongoTemplate mongoTemplate;

    protected void importJSON(String collection, String file) {
        try {
            for (String line : FileUtils.readLines(new File(file), "utf8")) {
                Document doc = Document.parse(line);
                mongoTemplate.save(doc, collection);
            }
        } catch (IOException e) {
            throw new RuntimeException("Could not import file: " + file, e);
        }
    }

}


@RunWith(Cucumber.class)
@CucumberOptions(format = "pretty",
                 features = "src/test/resources/features",
                 glue = "com.app.comment.cucumber")
public class CucumberIntegrationTest {
}


public class StepDefinitions extends SpringIntegrationTest {

    private Map<String, String> headerMap = null;
    private String postBody = null;
    private String putBody = null;
    private String formData = null;
    private Response response = null;
    private String data = null;

    private final static String MONGODB_COLLECTION = "comment";
    private final static String MONGODB_DATA = "src/test/resources/mongodb-data/data.txt";

    @Before
    public void setup() {
        importJSON(MONGODB_COLLECTION, MONGODB_DATA);
    }

    @Given("^the header information$")
    public void the_header_information(Map<String, String> headerMap) throws Throwable {
        this.headerMap = headerMap;
    }

    @Given("^post message body \"(.*?)\"$")
    public void post_message_body(String postBody) throws Throwable {
        this.postBody = postBody;
    }

    @Given("^put message body \"(.*?)\"$")
    public void put_message_body(String putBody) throws Throwable {
        this.putBody = putBody;
    }
}

pom.xml file:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.app.comment</groupId>
    <artifactId>app-comment-api</artifactId>
    <version>1.0.4</version>
    <packaging>jar</packaging>

    <name>app-comment-api</name>
    <description>App Comments Microservice</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <log4j.version>2.4.1</log4j.version>
        <commons.lang3.version>3.3.2</commons.lang3.version>
        <guava.version>19.0</guava.version>
        <swagger.version>2.4.0</swagger.version>
        <surefire.junit47.version>2.18.1</surefire.junit47.version>
        <rest-assured.version>2.8.0</rest-assured.version>
        <jacoco.version>0.7.5.201505241946</jacoco.version>
        <powermock.version>1.6.4</powermock.version>
        <commons.io.version>2.4</commons.io.version>
        <httpclient.version>4.5.1</httpclient.version>
        <jayway.jsonpath.version>2.2.0</jayway.jsonpath.version>
        <jjwt.version>0.6.0</jjwt.version>
        <docker.image.prefix>app</docker.image.prefix>
        <docker.spotify.plugin.version>0.4.5</docker.spotify.plugin.version>
        <jacoco.maven.plugin.version>0.7.7.201606060606</jacoco.maven.plugin.version>
        <fongo.version>2.0.11</fongo.version>
        <cucumber.version>1.2.5</cucumber.version>
        <gatling.highcharts.version>2.2.3</gatling.highcharts.version>
        <gatling.plugin.version>2.2.1</gatling.plugin.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-actuator-docs</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-ribbon</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-sleuth</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-sleuth-zipkin</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security.oauth</groupId>
            <artifactId>spring-security-oauth2</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-jwt</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>io.dropwizard.metrics</groupId>
            <artifactId>metrics-core</artifactId>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>${swagger.version}</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>${swagger.version}</version>
        </dependency>

        <!-- Utility -->
        <dependency>
            <groupId>com.logentries</groupId>
            <artifactId>logentries-appender</artifactId>
            <version>RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>${commons.io.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>${commons.lang3.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>${httpclient.version}</version>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>${guava.version}</version>
        </dependency>
        <dependency>
            <groupId>com.jayway.jsonpath</groupId>
            <artifactId>json-path</artifactId>
            <version>${jayway.jsonpath.version}</version>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>${jjwt.version}</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.datatype</groupId>
            <artifactId>jackson-datatype-jsr310</artifactId>
            <version>2.6.5</version>
        </dependency>

        <!-- Test Dependencies -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.powermock</groupId>
            <artifactId>powermock-module-junit4</artifactId>
            <version>${powermock.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.powermock</groupId>
            <artifactId>powermock-api-mockito</artifactId>
            <version>${powermock.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.jayway.restassured</groupId>
            <artifactId>rest-assured</artifactId>
            <version>${rest-assured.version}</version>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <artifactId>commons-logging</artifactId>
                    <groupId>commons-logging</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.jayway.restassured</groupId>
            <artifactId>spring-mock-mvc</artifactId>
            <version>${rest-assured.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>de.flapdoodle.embed</groupId>
            <artifactId>de.flapdoodle.embed.mongo</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>info.cukes</groupId>
            <artifactId>cucumber-java</artifactId>
            <version>${cucumber.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>info.cukes</groupId>
            <artifactId>cucumber-junit</artifactId>
            <version>${cucumber.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>info.cukes</groupId>
            <artifactId>cucumber-spring</artifactId>
            <version>${cucumber.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>io.gatling.highcharts</groupId>
            <artifactId>gatling-charts-highcharts</artifactId>
            <version>${gatling.highcharts.version}</version>
            <scope>test</scope>
        </dependency>

    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Camden.SR5</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <!-- Package as a docker image -->
            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>docker-maven-plugin</artifactId>
                <version>${docker.spotify.plugin.version}</version>
                <configuration>
                    <serverId>docker-hub</serverId>
                    <imageName>${docker.image.prefix}/${project.artifactId}</imageName>
                    <dockerDirectory>src/main/docker</dockerDirectory>
                    <resources>
                        <resource>
                            <targetPath>/</targetPath>
                            <directory>${project.build.directory}</directory>
                            <include>${project.build.finalName}.jar</include>
                        </resource>
                    </resources>
                    <imageTags>
                        <imageTag>${project.version}</imageTag>
                    </imageTags>
                </configuration>
            </plugin>
            <!-- Runs Code Coverage Reports -->
            <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <version>${jacoco.maven.plugin.version}</version>
                <executions>
                    <execution>
                        <id>pre-unit-test</id>
                        <goals>
                            <goal>prepare-agent</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>post-unit-test</id>
                        <phase>test</phase>
                        <goals>
                            <goal>report</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>**/*IntegrationTest.java</exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <profiles>
        <profile>
        <id>cucumber-tests</id>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <configuration>
                        <excludes>
                            <exclude>none</exclude>
                        </excludes>
                        <includes>
                            <!-- Include your Cucumber tests, as an example -->
                            <exclude>**/*IntegrationTest.java</exclude>
                            <exclude>**/*Simulation.scala</exclude>
                        </includes>
                    </configuration>
                </plugin>
            </plugins>
        </build>
        </profile>
        <profile>
            <id>gatling-tests</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>io.gatling</groupId>
                        <artifactId>gatling-maven-plugin</artifactId>
                        <version>${gatling.plugin.version}</version>
                        <executions>
                            <execution>
                                <goals>
                                    <goal>execute</goal>
                                </goals>
                                <configuration>
                                    <simulationClass>com.app.comment.gatling.MicroserviceServiceSimulation</simulationClass>
                                </configuration>
                            </execution>
                        </executions>
                        <configuration>
                            <configFolder>${project.basedir}/src/test/resources</configFolder>
                            <dataFolder>${project.basedir}/src/test/resources/data</dataFolder>
                            <resultsFolder>${project.basedir}/target/gatling/results</resultsFolder>
                            <bodiesFolder>${project.basedir}/src/test/resources/bodies</bodiesFolder>
                            <simulationsFolder>${project.basedir}/src/test/scala</simulationsFolder>
                            <runDescription>This-is-the-run-description</runDescription>
                            <!--    <noReports>false</noReports> -->
                            <!--   <reportsOnly>directoryName</reportsOnly> -->
                            <!--   <simulationClass>foo.Bar</simulationClass> -->
                            <!--   <jvmArgs> -->
                            <!--     <jvmArg>-DmyExtraParam=foo</jvmArg> -->
                            <!--   </jvmArgs> -->
                            <!--    <fork>true</fork> -->
                            <!--    <propagateSystemProperties>true</propagateSystemProperties> -->
                            <!--   <failOnError>true</failOnError> -->
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>

</project>

http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-testing-spring-boot-applications-testing-autoconfigured-mongo-test

3 Answers3

1

If you use JUnit 4, you should have RunWith(SpringRunner.class). With JUnit 5 is not necessary.

And, @SpringBootTest cannot coexist with @DataMongoTest, because they are for different parts of the application and the latter is only for data part, while the former is for app part. (Actually the @BootstrapWith of them will conflict if you put these two together and the test cannot be start)

@DataMongoTest will use embedded database and you don't need to do extra config other than @Autowired the mongotemplate. If you want to use real db, do this:

@DataMongoTest(excludeAutoConfiguration = EmbeddedMongoAutoConfiguration.class)

My test is like this and it works:

@ActiveProfiles("db")
@DataMongoTest
class CouponTypeRefRepositoryTest {

    @Autowired
    private CouponTypeRefRepository repository; // a simple repository extending `DataMongoRepository`

    @Autowired
    private MongoTemplate mongoTemplate;


    @BeforeEach
    void prepare() {
        CouponTypeRef toSave = CouponTypeRef.builder()
                .id((short)1)
                .duration((short)1)
                .couponType("COMMERCIAL")
                .couponTypeRefConfig(CouponTypeRefConfig.REFUNDABLE_NORMAL)
                .build();
        mongoTemplate.save(toSave, "CouponTypeRef");
    }

    @Test
    void shouldReturnCouponTypeRef() {
        Optional<CouponTypeRef> optional = repository.findById((short)1);
        assertThat(optional.isPresent(), is(true));
        assertThat(optional.get().getCouponType(), is("COMMERCIAL"));
        assertThat(optional.get().getDuration(), is((short)1));
        assertThat(optional.get().getCouponTypeRefConfig(), is(CouponTypeRefConfig.REFUNDABLE_NORMAL));
    }

My dependency is:

implementation 'org.springframework.boot:spring-boot-starter-data-mongodb-reactive:2.2.1.RELEASE'

The db profile config:

spring:
  data:
    mongodb:
      host: localhost
      port: 27017
      database: app1

More info here: https://www.baeldung.com/spring-boot-embedded-mongodb https://docs.spring.io/spring-boot/docs/1.5.4.RELEASE/reference/html/boot-features-testing.html

WesternGun
  • 11,303
  • 6
  • 88
  • 157
  • it work at first run that test, but somehow fails all other runs. – fuat Aug 10 '20 at 20:57
  • Maybe you should try testcontainer (run container of mongo) – WesternGun Aug 11 '20 at 09:14
  • `repository.save(entity) ` perfectly fine, but somehow `repository.findById(id)` failed. Maybe @DirtyContext might be useful for this situation. – fuat Aug 11 '20 at 10:53
  • Finally the problem is solved. You should better do `repository.save(entity)` in `@BeforeEach` function. That's the way to pass all tests. – fuat Aug 13 '20 at 04:28
0

Adding @RunWith(SpringRunner.class) annotation to SpringIntegrationTest class should work. SpringRunner will enable Autowiring of beans into your test class.

0

Try putting an @DirtiesContext on your test class.

Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
PCalouche
  • 1,605
  • 2
  • 16
  • 19