如何将 mongoclient 注入到我的 POST 服务中

huangapple go评论115阅读模式
英文:

How to inject mongoclient to my POST service

问题

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;
	}
}

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);
}
英文:

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

Controller:

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

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

Service Class:

@ApplicationScoped
public class B {

	@Inject 
	MongoClient mongoClient;

	private MongoCollection&lt;Document&gt; getCollection() {
		return mongoClient.getDatabase(DBname).getCollection(coll);
	}

	public Document add(List&lt;? extends Document&gt; list) {
		Document response = new Document();
		getCollection().deleteMany(new BasicDBObject());
		getCollection().insertMany(list);
		response.append(&quot;count&quot;, 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&lt;Document&gt; request = new ArrayList&lt;Document&gt;(); 
    Document doc = new Document();
    doc.append(&quot;Id&quot;, &quot;007&quot;)
       .append(&quot;name&quot;, &quot;Nitin&quot;);
    request.add(doc);
    
    given()
         .body(request)
         .header(&quot;Content-Type&quot;, MediaType.APPLICATION_JSON)
         .when()
         .post(&quot;/endpoint&quot;)
         .then()
         .statusCode(200);
}

答案1

得分: 2

你需要在测试中使用不同的连接字符串,而不是在常规(生产)运行中使用相同的连接字符串。

Quarkus 可以使用配置文件来实现这一点,当运行 @QuarkusTest 测试时,会自动选择 %test 配置文件。

因此,你可以在你的 application.properties 中添加类似以下的内容:

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

在正常运行应用程序时,mongodb://host:port 将被使用,而在测试中将使用 mongodb://localhost:27017

然后,你可以使用 Flapdoodle 或 Testcontainers 在测试期间在本地启动 MongoDB 数据库。

关于配置文件的更多信息:https://quarkus.io/guides/config#configuration-profiles

关于如何从 Quarkus 测试中启动外部服务的更多信息:https://quarkus.io/guides/getting-started-testing#quarkus-test-resource

英文:

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

答案2

得分: 1

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: https://stackoverflow.com/questions/6437226/embedded-mongodb-when-running-integration-tests

英文:

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 = &quot;embedded&quot;;
private MongodExecutable mongodExe;
private MongodProcess mongod;
private MongoClient mongo;
@Before
public void beforeEach() throws Exception {
MongodStarter starter = MongodStarter.getDefaultInstance();
String bindIp = &quot;localhost&quot;;
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(&quot;testCollection&quot;);
MongoCollection&lt;BasicDBObject&gt; col = db.getCollection(&quot;testCollection&quot;, BasicDBObject.class);
// when
col.insertOne(new BasicDBObject(&quot;testDoc&quot;, new Date()));
// then
assertEquals(1L, col.countDocuments());
}
}

Reference : https://stackoverflow.com/questions/6437226/embedded-mongodb-when-running-integration-tests

答案3

得分: 0

感谢大家的建议。我在application.properties文件中声明了测试集合。当我们运行junit时,%test配置文件会自动激活,因此我的服务会自动选择测试集合。在我的junit测试用例完成后,我删除了测试集合。

英文:

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.

huangapple
  • 本文由 发表于 2020年8月12日 05:11:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/63366427.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定