How to use custom converters with @DataMongoTest?
Asked Answered
T

3

10

I have a test instantiating some entities, saving them to MongoDB and loading them again to make sure the mapping works corretly. I'd like to use the @DataMongoTest annotation on the test class to make sure an embedded MongoDB instance is dynamically created.

This worked just fine until I had to introduce custom converters (org.springframework.core.convert.converter.Converter) for some classes. These are set up like this:

@ReadingConverter
public class MyClassReadConverter implements Converter<Document, MyClass> {
...

@WritingConverter
public class MyClassWriteConverter implements Converter<MyClass, Document> {
...

@Configuration
public class SpringMongoSetup extends AbstractMongoConfiguration {
    @Override
    public Mongo mongo() throws Exception {
        //I don't want that in the test..
        return new MongoClient("localhost"); 
    }

    @Override
    public CustomConversions customConversions() {
        // ..but I need this
        List<Converter<?,?>> converters = new ArrayList<>();
        converters.add(new MyClassWriteConverter());
        converters.add(new MyClassReadConverter());
        return new CustomConversions(converters);
    }
...

For normal (non-test) execution this works just fine. The test also works if I use the @SpringBootTest annotation which makes the test use my configuration. Unfortunately, this configuration also defines the host/port for MongoDB, but I'd like to use the host/port of the embedded MongoDB started by @DataMongoTest.

Can I somehow configure it so that either @DataMongoTest uses the custom converters with the embedded MongoDB, or that I can get the embedded host/port while instantiating my configuration class?

Tysontyumen answered 7/2, 2017 at 16:13 Comment(1)
To give more context to this old question - is there a way to separate connection string and mongo converters configuration? Can you have one without another during testing using possibly in-memory db? Or does it have to be integration test with a real db?Zoubek
V
6

To use CustomConverters with @DataMongoTest you need to expose those converters as a Spring bean, e.g.:

@Configuration 
public class CustomConversionsConfiguration {

    @Bean
    public CustomConversions customConversions() {
        List<Converter<?,?>> converters = new ArrayList<>();
        converters.add(new MyClassWriteConverter());
        converters.add(new MyClassReadConverter());
        return new CustomConversions(converters);
    }

}

...and use the configuration in Mongo test classes:

@RunWith(SpringRunner.class)
@DataMongoTest
@Import(CustomConversionsConfiguration.class)
public class MyMongoTest { ... }
Villada answered 18/6, 2020 at 20:13 Comment(1)
I don't know if it's because of Kotlin or a future version, but I've had to return MongoCustomConversions specifically for it to work.Yorgo
M
0

If you are using slicing we will disable all scanning that isn't relevant to Mongo. We have no way to know that your SpringMongoSetup is related to Mongo so, since we don't scan it, it's not applied.

If you do not rely on the auto-configuration for Mongo, you'll have to import that class yourself. You can do so with @Import, e.g.

@RunWith(SpringRunner.class)
@DataMongoTest
@Import(SpringMongoSetup.class)
public class MyMongoTest { ... }
Martini answered 7/2, 2017 at 16:44 Comment(1)
That also uses the host/ip configured in SpringMongoSetup. (I omited the @Override public Mongo mongo() {..} part in the question, because it's mandatory for AbstractMongoConfiguration - I have edited it now) How can I override that to use the embedded MongoDB launched by @DataMongoTest?Spite
S
0

I think the recommended way is (using junit5):

@DataMongoTest
@ContextConfiguration(classes = MongoConfig.class)
public class MyMongoTest { ... }

In your MongoConfig.class you have the configuration that your actual application uses.

Sonny answered 12/1, 2024 at 8:55 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.