4

I have a Spring Boot REST service and some unit tests written for the data layer. I use the embedded MongoDB dependency to perform the basic CRUD tests for my Repository class:

public interface UserRepository extends MongoRepository<UserEntity, String> {
    Optional<UserEntity> findByUsername(String username);
}

I load the data from a JSON file (located under test/java/resources/data) and with the help of an ObjectMapper instance, I load the data into the embedded DB before each test and drop the collection after it's completed:

@DataMongoTest
class UserRepositoryTest {

    // the path to the JSON file
    private final File USER_DATA_JSON = Paths.get("src", "test", "resources", "data", "UserData.json").toFile();

    // used to load a JSON file into a list of Users
    private final ObjectMapper objectMapper = new ObjectMapper();

    @Autowired
    private MongoTemplate mongoTemplate; // makes the interaction with the embedded MongoDB much easier

    @Autowired
    private UserRepository userRepository;

    @BeforeEach
    void setUp() throws IOException {
        // deserialize the JSON file to an array of users
        UserEntity[] users = objectMapper.readValue(USER_DATA_JSON, UserEntity[].class);

        // load each user into embedded MongoDB
        Arrays.stream(users).forEach(mongoTemplate::save);
    }

    @AfterEach
    void tearDown() {
        // drop the users collection
        mongoTemplate.dropCollection("users");
    }

    @Test
    void testFindAllSuccess() {
        // WHEN
        List<UserEntity> users = userRepository.findAll();

        // THEN
        assertEquals(2, users.size(), "findAll() should return 2 users!");
    }

    // other test methods
}

In my local environment, everything works just fine, no configuration is needed inside the application.properties file. But when I execute a build on Jenkins, the following error appears for all the Repository tests:

UserRepositoryTest > testFindAllSuccess() FAILED
java.lang.IllegalStateException at DefaultCacheAwareContextLoaderDelegate.java:132
    Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException at ConstructorResolver.java:800
        Caused by: org.springframework.beans.factory.BeanCreationException at ConstructorResolver.java:658
            Caused by: org.springframework.beans.BeanInstantiationException at SimpleInstantiationStrategy.java:185
                Caused by: java.net.UnknownHostException at InetAddress.java:1642
                    Caused by: java.net.UnknownHostException at Inet6AddressImpl.java:-2

The build.gradle file dependencies are declared as follows:

implementation 'org.openapitools:openapi-generator-gradle-plugin:5.0.0'
implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation "io.springfox:springfox-boot-starter:3.0.0"
implementation('org.modelmapper:modelmapper:2.3.0')
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'de.flapdoodle.embed:de.flapdoodle.embed.mongo'
testImplementation 'io.projectreactor:reactor-test'
compile 'io.springfox:springfox-swagger-ui:3.0.0'
annotationProcessor group: 'org.springframework.boot', name: 'spring-boot-configuration-processor'
compile 'org.mongodb:mongodb-driver-sync'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.security:spring-security-test'
// https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt
implementation group: 'io.jsonwebtoken', name: 'jjwt', version: '0.9.1'

I assume Spring Boot is not identifying the embedded MongoDB anymore. How can I configure it as simple as possible?

I saw there is a possibility of using containerized MongoDB and test it using @TestContainers, but for now I need to fix this issue since every build fails due to the tests.

LATER EDIT: By activating the --debug option in Jenkins when running the build, I discovered the following cause:

java.net.UnknownHostException: dev096.dev.cloud.******.eu: dev096.dev.cloud.******.eu: Name or service not known

Do you know if I have to add that address to the known hosts to my local machine (etc/hosts) or it should be configured locally with profiles (localhost for development and dev096.dev.cloud.******.eu for production)?

  • 1
    Hi! I have some time to look into this today, but being a complex issue could you join me on discord so we can communicate more easily? https://discord.gg/wNXWqe7dMS – Andy Valerio Mar 23 '21 at 09:06
  • 2
    Use difference profiles, for testing the test profile should be used. and in test profile the localhost is the desired host for your tests. Otherwise just make the access available for these unknown hosts and this still should work. – muasif80 Mar 26 '21 at 06:23

3 Answers3

3

I managed to reproduce the same error locally and, if you haven't solved it yet, this is my take.

Remove all MongoDB custom configurations/properties, then add the following class to your project:

@Configuration
public class MongoTestConfig {

    @Bean
    MongoProperties properties() {
        MongoProperties mongoProperties = new MongoProperties();
        mongoProperties.setPort(33333);
        mongoProperties.setHost("localhost");
        return mongoProperties;
    }
}

Make sure you tag your test class (UserRepositoryTest) with these three annotations:

@RunWith(SpringRunner.class)
@DataMongoTest
@Import(MongoTestConfig.class)

@DataMongoTest ignores all other bean definitions so we force the test to include the configuration that we just created using the explicit @Import.

Now the test will be forced to run on localhost. Hope it's going to work for you as it did for me!

Andy Valerio
  • 851
  • 6
  • 13
2

If dev096.dev.cloud.******.eu is a host used only in production, then your production server needs to know that host; not your local PC, nor Jenkins.

Ideally, you'd run your Jenkins tests using a 'jenkins' Spring profile, and then define the localhost in application-jenkins.properties.

Simon
  • 2,994
  • 3
  • 28
  • 37
1

Unfortunately, none of your solutions worked for me, but I found out later that dev096.dev.cloud.******.eu is the Jenkins instance itself.

The fix was to add an entry in /etc/hosts/ such that the server's IP to be also recognized as dev096.dev.cloud.******.eu