Mowgli
Mowgli

Reputation: 73

How to inject mongoclient to my POST service

I have a very simple Quarkus application which accepts input and insert it into MongoDB using MongoClient.

Controller:

@ApplicationScoped
@Path("/endpoint")
public class A {
    @Inject 
    B service;

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public Document add(List<? extends Document> list) {
        return service.add(list);
    }
}

Service Class:

@ApplicationScoped
public class B {

    @Inject 
    MongoClient mongoClient;

    private MongoCollection<Document> getCollection() {
        return mongoClient.getDatabase(DBname).getCollection(coll);
    }

    public Document add(List<? extends Document> list) {
        Document response = new Document();
        getCollection().deleteMany(new BasicDBObject());
        getCollection().insertMany(list);
        response.append("count", list.size());
        return response;
    }
}

As you see that my service removes existing data and inserts the new data. For JUnit testing, I am trying to set up embedded MongoDB and want my service call to use the embedded mongo. But no success.

My JUnit class

I tried out many approaches discussed on the internet to set up the embedded mongo but none worked for me.

I want to invoke my POST service but actual mongodb must not get connected. My JUnit class is as below:

@QuarkusTest
public class test {
    List<Document> request = new ArrayList<Document>(); 
    Document doc = new Document();
    doc.append("Id", "007")
       .append("name", "Nitin");
    request.add(doc);
    
    given()
         .body(request)
         .header("Content-Type", MediaType.APPLICATION_JSON)
         .when()
         .post("/endpoint")
         .then()
         .statusCode(200);
}

Upvotes: 2

Views: 881

Answers (3)

Mowgli
Mowgli

Reputation: 73

Thanks everyone for suggestions. I declared test collections in application.properties file. %test profile automatically get activated when we run junits, so automatically my services picked up the test collections. I deleted the test collections after my junit test cases got completed.

Upvotes: 0

loicmathieu
loicmathieu

Reputation: 5562

You need to use a different connection-string for your test than for your regular (production) run.

Quakus can use profiles to do this, the %test profile is automatically selected when running @QuarkusTest tests.

So you can add in your application.properties something like this :

quarkus.mongodb.connection-string=mongodb://host:port
%test.quarkus.mongodb.connection-string=mongodb://localhost:27017

Here mongodb://host:port will be use on the normal run of your application and mongodb://localhost:27017 will be used from inside your test.

Then you can use flapdoodle or Testcontainers to launch a MongoDB database on localhost during your test.

More information on configuration profiles: https://quarkus.io/guides/config#configuration-profiles

More information on how to start an external service from a Quarkus test: https://quarkus.io/guides/getting-started-testing#quarkus-test-resource

Upvotes: 2

suraj shukla
suraj shukla

Reputation: 106

Have u tried flapdoodle:

package com.example.mongo;

import com.mongodb.BasicDBObject;
import com.mongodb.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import de.flapdoodle.embed.mongo.MongodExecutable;
import de.flapdoodle.embed.mongo.MongodProcess;
import de.flapdoodle.embed.mongo.MongodStarter;
import de.flapdoodle.embed.mongo.config.IMongodConfig;
import de.flapdoodle.embed.mongo.config.MongodConfigBuilder;
import de.flapdoodle.embed.mongo.config.Net;
import de.flapdoodle.embed.mongo.distribution.Version;
import de.flapdoodle.embed.process.runtime.Network;
import java.util.Date;
import org.junit.After;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;

public class EmbeddedMongoTest
{
    private static final String DATABASE_NAME = "embedded";

    private MongodExecutable mongodExe;
    private MongodProcess mongod;
    private MongoClient mongo;

    @Before
    public void beforeEach() throws Exception {
        MongodStarter starter = MongodStarter.getDefaultInstance();
        String bindIp = "localhost";
        int port = 12345;
        IMongodConfig mongodConfig = new MongodConfigBuilder()
        .version(Version.Main.PRODUCTION)
        .net(new Net(bindIp, port, Network.localhostIsIPv6()))
        .build();
        this.mongodExe = starter.prepare(mongodConfig);
        this.mongod = mongodExe.start();
        this.mongo = new MongoClient(bindIp, port);
    }

    @After
    public void afterEach() throws Exception {
        if (this.mongod != null) {
            this.mongod.stop();
            this.mongodExe.stop();
        }
    }

    @Test
    public void shouldCreateNewObjectInEmbeddedMongoDb() {
        // given
        MongoDatabase db = mongo.getDatabase(DATABASE_NAME);
        db.createCollection("testCollection");
        MongoCollection<BasicDBObject> col = db.getCollection("testCollection", BasicDBObject.class);

        // when
        col.insertOne(new BasicDBObject("testDoc", new Date()));

        // then
        assertEquals(1L, col.countDocuments());
    }

}

Reference : Embedded MongoDB when running integration tests

Upvotes: 1

Related Questions