@DataMongoTest is creating a null MongoTemplate
Asked Answered
P

3

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

Presumably answered 18/2, 2017 at 15:47 Comment(0)
C
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

Clave answered 2/3, 2020 at 11:51 Comment(4)
it work at first run that test, but somehow fails all other runs.Pennsylvanian
Maybe you should try testcontainer (run container of mongo)Clave
repository.save(entity) perfectly fine, but somehow repository.findById(id) failed. Maybe @DirtyContext might be useful for this situation.Pennsylvanian
Finally the problem is solved. You should better do repository.save(entity) in @BeforeEach function. That's the way to pass all tests.Pennsylvanian
S
0

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

Snocat answered 26/2, 2019 at 20:19 Comment(0)
B
0

Try putting an @DirtiesContext on your test class.

Beckibeckie answered 5/5, 2022 at 13:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.