Testcontainersを使ってFirestoreのユニットテストをする
以下のようなベースクラスを継承してユニットテストを書くと便利。
open class FirestoreTestBase {
protected lateinit var firestore: Firestore
@BeforeEach
open fun beforeEach() {
firestore = FirestoreOptions.getDefaultInstance().toBuilder()
.setEmulatorHost(CONTAINER.emulatorEndpoint)
.setCredentials(FirestoreOptions.EmulatorCredentials())
.setProjectId("test-project")
.build()
.service
}
@AfterEach
open fun afterEach() {
firestore.listCollections().forEach { collectionRef ->
deleteCollection(collectionRef, DELETE_BATCH_SIZE)
}
firestore.close()
}
/**
* ここに書いてあるやりかた。
* ref: https://firebase.google.com/docs/firestore/manage-data/delete-data?hl=ja#collections
*
* なお、こういう方法もあるようだ。
* https://firebase.google.com/docs/emulator-suite/connect_firestore?hl=ja
*/
private fun deleteCollection(collection: CollectionReference, batchSize: Int) {
try {
// retrieve a small batch of documents to avoid out-of-memory errors
val documents = collection.limit(batchSize).get().get().documents
var deleted = 0
documents.forEach { document ->
document.reference.delete()
++deleted
}
if (deleted >= batchSize) {
// retrieve and delete another batch
deleteCollection(collection, batchSize)
}
} catch (e: Exception) {
log.error("Error deleting collection", e)
}
}
companion object {
private val log = KotlinLogging.logger {}
private val CONTAINER = FirestoreEmulatorContainer(
DockerImageName.parse("gcr.io/google.com/cloudsdktool/cloud-sdk:381.0.0-emulators")
).apply {
start()
log.info("Start firebase container. endpoint={}", emulatorEndpoint)
}
private const val DELETE_BATCH_SIZE = 1000
}
}
なおTestcontainersの 公式ドキュメント では以下のようにしているが、
FirestoreOptions.getDefaultInstance().toBuilder()
.setHost(CONTAINER.emulatorEndpoint)
.setCredentials(NoCredentials.getInstance())
このようにしておかないと firestore.listCollections()
等が認証不足?で呼び出せないので注意。
FirestoreOptions.getDefaultInstance().toBuilder()
.setEmulatorHost(CONTAINER.emulatorEndpoint)
.setCredentials(FirestoreOptions.EmulatorCredentials())
最終更新日:
2022/04/19 02:30