LoginSignup
1
1

More than 1 year has passed since last update.

ncmb_kotlin テスト構造について

Posted at

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でテスト実行を選択し、行います。ファイルごとに、メソッドごとに、フォルダーごとにどちらでも可能。

image.png

Kotlin SDKのテスト構成

image.png

  • モック制御する部分
    • 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
    コールバック内の結果のチェックを実施するために、スレッドを一時的に止めるように処理します。

テストを書く時に必要なこと

  • 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)
    }

参考

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1