0

I have a Spring Boot application which use MongoDB. I would like to use the embedded FongoDB for my JUnit tests. I follow some articles, for example:

http://dontpanic.42.nl/2015/02/in-memory-mongodb-for-unit-and.html

My Fongo test configuration looks like

package com.myproject.rest;

import com.github.fakemongo.Fongo;
import com.mongodb.Mongo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.data.mongodb.config.AbstractMongoConfiguration;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;

@Profile("test")
@ComponentScan(basePackages = "com.myproject.service.data")
@EnableMongoRepositories(basePackages = "com.myproject.service.data.repository")
@Configuration
public class MongoTestConfig extends AbstractMongoConfiguration {

    @Override
    protected String getDatabaseName() {
        return "demo-test";
    }

    @Bean
    @Override
    public Mongo mongo() {
        return new Fongo("mongo-test").getMongo();
    }

}

I have this dependency for that:

        <dependency>
            <groupId>com.github.fakemongo</groupId>
            <artifactId>fongo</artifactId>
            <version>2.1.0</version>
            <scope>test</scope>
        </dependency>

I would like to test my services which autowired a repository interface which extends MongoRepository

package com.myproject.service.data.repository;

import com.myproject.service.data.entity.JournalData;
import org.springframework.data.mongodb.repository.MongoRepository;

import java.util.List;

public interface JournalRepository extends MongoRepository<JournalData, String> {

    @Override
    public List<JournalData> findAll(Iterable<String> ids);
}

My tests class are inherited from the class below:

package com.myproject.rest;

import com.lordofthejars.nosqlunit.mongodb.MongoDbRule;
import cz.csas.services.commons.api.RequestMetadata;
import org.junit.Before;
import org.junit.Rule;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.modules.junit4.PowerMockRunnerDelegate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.MockMvc;

import static org.mockito.Mockito.when;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static com.lordofthejars.nosqlunit.mongodb.MongoDbRule.MongoDbRuleBuilder.newMongoDbRule;

@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
@PowerMockIgnore({"javax.xml.*", "org.xml.*", "org.w3c.*", "javax.management.*", "javax.net.ssl.*"})
@PrepareForTest({RequestMetadata.class})
@ActiveProfiles("test")
public class EndpointTestContext {

    @Autowired
    protected MockMvc mockMvc;

    //@Rule
    //public MongoDbRule mongoDbRule = newMongoDbRule().defaultSpringMongoDb("demo-test");

    @Before
    public void setup() {
        mockStatic(RequestMetadata.class);
        when(RequestMetadata.builder()).thenCallRealMethod();
        RequestMetadata m = RequestMetadata.builder()
                .workingMode("TEST")
                .build();
        when(RequestMetadata.getMetadata()).thenReturn(m);
    }

}

But when I run the Maven tests I recieve the following:

Caused by: java.lang.NoClassDefFoundError: Could not initialize class com.mongodb.MongoClientOptions
    at com.mongodb.MockMongoClient.create(MockMongoClient.java:42)
    at com.github.fakemongo.Fongo.createMongo(Fongo.java:175)
    at com.github.fakemongo.Fongo.<init>(Fongo.java:88)
    at com.github.fakemongo.Fongo.<init>(Fongo.java:75)
    at com.github.fakemongo.Fongo.<init>(Fongo.java:67)
    at com.myproject.rest.MongoTestConfig.mongo(MongoTestConfig.java:30)
    at com.myproject.rest.MongoTestConfig$$EnhancerBySpringCGLIB$$bf18b1d4.CGLIB$mongo$1(<generated>)
    at com.myproject.rest.MongoTestConfig$$EnhancerBySpringCGLIB$$bf18b1d4$$FastClassBySpringCGLIB$$3ab8bfd7.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358)
    at com.myproject.rest.MongoTestConfig$$EnhancerBySpringCGLIB$$bf18b1d4.mongo(<generated>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162)
    ... 115 common frames omitted

Can anyone suggest how to fix it? Thank you in advance.

2 Answers2

0

Fongo can't find class from mongo-java-driver artifact. It declares

<!-- https://mvnrepository.com/artifact/org.mongodb/mongo-java-driver -->
<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongo-java-driver</artifactId>
    <version>3.4.2</version>
</dependency>

as provided dependency. You should have mongo-java-driver on your test classpath. Most probably

<scope>runtime</scope>

or test will be enough for you.

Aleh Maksimovich
  • 2,622
  • 8
  • 19
0

Check if you have multiple version of mongo java driver (version conflicts). To check this, you can use mvn dependency tree to trace the path from where each jar is coming to your project.

mvn dependency:tree

Just need to find out the right version on mongo java driver and make sure you are not having version conflicts. I have used spring data and used fongo to write in-memory test case for mongodb queries.

<fongo-version>1.6.3</fongo-version>
<spring-data-mongodb-version>1.7.2.RELEASE</spring-data-mongodb-version>
<spring-framework-version>4.1.5.RELEASE</spring-framework-version>

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-mongodb</artifactId>
    <version>${spring-data-mongodb-version}</version>
  </dependency>
<dependency>
    <groupId>com.github.fakemongo</groupId>
    <artifactId>fongo</artifactId>
    <version>${fongo-version}</version>
    <scope>test</scope>
  </dependency>

Version conflict can come from may source (can confirm using above mvc dependency:tree command, one such source is mongobee, so if you are using it, please exclude mongo-java-drive by using exclusion

<dependency>
    <groupId>com.github.mongobee</groupId>
    <artifactId>mongobee</artifactId>
    <version>${mongobee-version}</version>
    <exclusions>
      <exclusion>
        <groupId>org.mongodb</groupId>
        <artifactId>mongo-java-driver</artifactId>
      </exclusion>
    </exclusions>
  </dependency>
lrathod
  • 1,094
  • 1
  • 9
  • 17