sql >> データベース >  >> NoSQL >> MongoDB

SpringBootでFlapdoodleEmbeddedMongoDBを使用して@Transactionalをテストする

    レプリカセットの作成に関する情報は、こちら にあります。

    私のKotlinソリューション:

    import com.mongodb.BasicDBList
    import com.mongodb.BasicDBObjectBuilder
    import com.mongodb.DBObject
    import com.mongodb.client.MongoClient
    import com.mongodb.client.MongoClients
    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.MongoCmdOptionsBuilder
    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 org.assertj.core.api.Assertions.assertThat
    import org.bson.Document
    import org.junit.jupiter.api.Test
    import org.springframework.data.mongodb.MongoDatabaseFactory
    import org.springframework.data.mongodb.MongoTransactionManager
    import org.springframework.data.mongodb.core.MongoTemplate
    import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory
    import org.springframework.test.context.ActiveProfiles
    import org.springframework.transaction.TransactionStatus
    import org.springframework.transaction.support.TransactionCallbackWithoutResult
    import org.springframework.transaction.support.TransactionTemplate
    import java.io.IOException
    
    
    @ActiveProfiles("test")
    
    class EmbeddedMongoDbTransactionTest {
        private val CONNECTION_STRING = "mongodb://%s:%d/"  
    
        private var node1MongodExe: MongodExecutable? = null
        private var node1Mongod: MongodProcess? = null
        private var mongo: MongoClient? = null
        private var node2MongodExe: MongodExecutable? = null
        private var node2Mongod: MongodProcess? = null
    
        @Test
        @Throws(IOException::class)
        fun testSmth() {
            val runtime = MongodStarter.getDefaultInstance()
            val node1Port = 57023
            val node2Port = 57024
            try {
                node1MongodExe = runtime.prepare(
                    MongodConfigBuilder().version(Version.Main.PRODUCTION)
                        .withLaunchArgument("--replSet", "rs0")
                        .cmdOptions(MongoCmdOptionsBuilder().useNoJournal(false).build())
                        .net(Net(node1Port, Network.localhostIsIPv6())).build()
                )
                node1Mongod = node1MongodExe?.start()
                node2MongodExe = runtime.prepare(
                    MongodConfigBuilder().version(Version.Main.PRODUCTION)
                        .withLaunchArgument("--replSet", "rs0")
                        .cmdOptions(MongoCmdOptionsBuilder().useNoJournal(false).build())
                        .net(Net(node2Port, Network.localhostIsIPv6())).build()
                )
                node2Mongod = node2MongodExe?.start()
                mongo = MongoClients.create(CONNECTION_STRING.format("localhost", node1Port))
                val adminDatabase: MongoDatabase = mongo!!.getDatabase("admin")
    
                val config = Document("_id", "rs0")
                val members = BasicDBList()
                members.add(Document("_id", 0).append("host", "localhost:$node1Port"))
                members.add(Document("_id", 1).append("host", "localhost:$node2Port"))
                config.put("members", members)
    
                adminDatabase.runCommand(Document("replSetInitiate", config))
    
                println(">>>>>> wait")
                println(">>>>>>>>" + adminDatabase.runCommand(Document("replSetGetStatus", 1)))
                Thread.sleep(15_000) // without waiting fails with error : 'not master' on server
    
                val funDb: MongoDatabase = mongo?.getDatabase("fun")!!
    
                // insert test 1
                val testCollection: MongoCollection<Document> = funDb.getCollection("test")
                println(">>>>>>>> inserting data")
                testCollection.insertOne(Document("fancy", "value"))
                println(">>>>>>>> finding data")
                assertThat(testCollection.find().first()!!.get("fancy")).isEqualTo("value")
    
    
                // insert test 2 (with transaction)
                val mongoTemplate = MongoTemplate(mongo!!, "test")
    
                // Without creating collection in advance fails with error:
                // Cannot create namespace in multi-document transaction
                // (https://stackoverflow.com/questions/52585715/cannot-create-namespace-in-multi-document-transactionmongodb-4-0-spring-data-2)
                mongoTemplate.createCollection("collection")
    
                val mongoDatabaseFactory: MongoDatabaseFactory = SimpleMongoClientDatabaseFactory(mongo!!, "test")
                val mongoTransactionManager = MongoTransactionManager(mongoDatabaseFactory)
    
                val transactionTemplate = TransactionTemplate(mongoTransactionManager)
    
                transactionTemplate.execute(object : TransactionCallbackWithoutResult() {
                    override fun doInTransactionWithoutResult(status: TransactionStatus) {
                        val objectToSave = BasicDBObjectBuilder.start()
                            .add("key", "value")
                            .get()
    
                        // when
                        mongoTemplate.save(objectToSave, "collection")
    
                        // then
                        assertThat(mongoTemplate.findAll(DBObject::class.java, "collection"))
                            .extracting("key")
                            .containsOnly("value")
                    }
                })
    
                // after transaction
                assertThat(mongoTemplate.findAll(DBObject::class.java, "collection"))
                    .extracting("key")
                    .containsOnly("value")
    
            } finally {
                println(">>>>>> shutting down")
                mongo?.close()
                node1MongodExe?.stop()
                node1Mongod?.stop()
                node2MongodExe?.stop()
                node2Mongod?.stop()
            }
        }
    }
    



    1. HTMLを使用したMongoDBドキュメントの表示

    2. 結合された結果を持つ要素のMongodbルックアップ配列

    3. 例外:BSONタイプEOOから日付に変換できません

    4. 'メッセージ'リスナーでRedisを削除する方法