Kotlin SDKのテストについて
今回先日リリースしましたmobile backendのKotlin SDKのテストについて紹介となります。KotlinのUnit testやモックサーバなどのことが中心にテストを追加するケースごとのサンプルの紹介も記載しています。SDKのテストってどんなことなのか、モックサーバーの使い方などご参考になればかと思います。ご意見がある方はぜひコメントもお待ちしております。
利用するライブラリー
- テストでは以下のライブラリを利用しています。
- JUnit
- robolectric
- okhttp3.mockwebserver
テストコード実行方法
- テストケースは、'src/test/java/com/nifcloud/mbaas/core/'フォルダー内に格納されています。
- Robolectricを利用するため、テストクラスの前に以下の記載が必要
@RunWith(RobolectricTestRunner::class)
また、テストメソッドの前に以下のように記載してください。
@Test
fun testAbc(){
}
- 実行する際、Android Studioでテスト実行を選択し、行います。ファイルごとに、メソッドごとに、フォルダーごとにどちらでも可能。
Kotlin SDKのテスト構成
- モック制御する部分
- ymlファイル:src/test/assets/yaml/mbaas***.yml リクエストレスポンスのマッピングファイル
- 例
request:
url: /2013-09-01/classes/TestClass
method: POST
body:
key: value
response:
status: 201
file: valid_post_response.json
- リクエストレスポンスファイル(複数):src/test/assets/json(NCMBDispatcher用), src/test/assets/json_error(NCMBErrorDispatcher用)
- 例
{"objectId":"7FrmPTBKSNtVjajm","createDate":"2014-06-03T11:28:30.348Z"}
-
メイン処理:ymlファイルを読み込み、受けているリクエストの情報とymlファイル設定情報を比較し、該当するレスポンスファイルをMockResponse()として返却します。
- 正常リクエスト用NCMBDispatcher.kt(ncmb_kotlin/src/test/java/com/nifcloud/mbaas/core/)
- 例外リクエスト用 NCMBErrorDispatcher.kt(ncmb_kotlin/src/test/java/com/nifcloud/mbaas/core/)
-
その他
- 非同期処理のcallbackをテストするためのhelperクラス:
ncmb_kotlin/src/test/java/com/nifcloud/mbaas/core/helper/NCMBInBackgroundTestHelper.kt
コールバック内の結果のチェックを実施するために、スレッドを一時的に止めるように処理します。
- 非同期処理のcallbackをテストするためのhelperクラス:
テストを書く時に必要なこと
- API利用メソッドのテストに関しては、サーバモックを利用するために、
以下のようにモックを定義しています。
private var mServer: MockWebServer = MockWebServer()
-
@Before
処理で、必要な初期化設定を行います
@Before
fun setup() {
val ncmbDispatcher = NCMBDispatcher()
mServer.dispatcher = ncmbDispatcher
mServer.start()
NCMB.initialize(
RuntimeEnvironment.application.getApplicationContext(),
"appKey",
"cliKey",
mServer.url("/").toString(),
"2013-09-01"
)
callbackFlag = false;
}
- 同期処理テスト
@Test
@Throws(NCMBException::class)
fun save_object_with_post_data_save_success() {
var obj = NCMBObject("TestClass")
obj.put("key", "value")
obj = obj.save()
Assert.assertEquals(obj.getObjectId(), "7FrmPTBKSNtVjajm")
}
- 非同期処理
@Test
fun saveInBackground_object_with_post_data_save_success() {
val inBackgroundHelper = NCMBInBackgroundTestHelper() // ヘルパーの初期化
val obj = NCMBObject("TestClass")
val callback = NCMBCallback { e, ncmbObj ->
inBackgroundHelper["e"] = e
inBackgroundHelper["ncmbObj"] = ncmbObj
inBackgroundHelper.release() // ブロックをリリース
}
obj.put("key", "value")
inBackgroundHelper.start()
obj.saveInBackground(callback)
inBackgroundHelper.await()
print("Success saved: ObjectID " + (inBackgroundHelper["ncmbObj"] as NCMBObject).getObjectId() + " | Response data: CreateDate " + (inBackgroundHelper["ncmbObj"] as NCMBObject).getCreateDate())
Assert.assertTrue(inBackgroundHelper.isCalledRelease())
Assert.assertNull(inBackgroundHelper["e"])
Assert.assertEquals((inBackgroundHelper["ncmbObj"] as NCMBObject).getObjectId(), "7FrmPTBKSNtVjajm")
val date: Date = getIso8601().parse("2014-06-03T11:28:30.348Z")!!
Assert.assertEquals((inBackgroundHelper["ncmbObj"] as NCMBObject).getCreateDate(), date)
}
エラーのテスト
- ケース1:SDKの処理内のエラー
@Test
fun test_geopoint_wrong_latitude(){
try {
val latitude: Double = 139.765607
val longitude: Double = 139.765607
val geopoint = NCMBGeoPoint(latitude, longitude)
}
catch(e: NCMBException){
Assert.assertEquals(e.message, "set the latitude to a value between -90 and 90")
}
}
- ケース2:同期処理のエラー
@Test
@Throws(Exception::class)
fun testNCMBObject_DoSearchSync_503error() {
//TestClassクラスを検索するクエリを作成
val query = NCMBQuery.forObject("TestClass503")
val throwable = assertFails{ val objects = query.find() }
Assert.assertEquals("Service unavailable.",throwable.message)
}
- ケース3: 非同期処理のエラー
@Test
@Throws(java.lang.Exception::class)
fun loginInBackground_invalid_username() {
val inBackgroundHelper = NCMBInBackgroundTestHelper() // ヘルパーの初期化
val callback = NCMBCallback { e, ncmbUser ->
inBackgroundHelper["e"] = e
inBackgroundHelper["ncmbUser"] = ncmbUser
inBackgroundHelper.release() // ブロックをリリース
}
inBackgroundHelper.start()
NCMBUser().loginInBackground("invalidUser", "Password", callback)
inBackgroundHelper.await()
Assert.assertTrue(inBackgroundHelper.isCalledRelease())
Assert.assertNull(NCMBUser().getCurrentUser().getObjectId())
Assert.assertEquals(NCMBException.AUTH_FAILURE, (inBackgroundHelper["e"] as NCMBException).code)
}
参考