android.util.PairはUnitテストではfirst==null & second==null になる

# 環境
- `androidx.core.core` : v1.9.0
- kotlin : v1.8.10
- `compileSDK` : 33
- `org.robolectric:robolectric` : v4.10.3

# 起きたこと
```kotlin
class ExampleUnitTest {
    @Test
    fun testA() {
        val pair = Pair(1, 2)

        assert(pair.first == 1)
        assert(pair.second == 2)

    }
}
```

こんなテストを、実行するとなぜか失敗。

# 原因

→原因は、ここで呼んでいた`Pair`が`android.util.Pair`だったから。

```kotlin
import android.util.Pair

class ExampleUnitTest {
    @Test
    fun testA() {
        val pair = Pair(1, 2)

        assert(pair.first == 1)
        assert(pair.second == 2)

    }
}

```

# Pairについて
Androidアプリを作成する際に使える`Pair`には`android.util.Pair`と`androidx.core.util.Pair`と`kotlin.Pair`があります。

全て(Kotlinから使う場合)コンストラクタ`Pair<F,S>(F first, S second)`を使用してインスタンスを作れますが、`android.util.Pair`だけは、そのコンストラクタを使用してインスタンスを作っても**Unitテストでは`first`や`second`は引数に渡したものにならずnullになるみたいです。** 注意。

## 成功するテスト(各`Pair`の`first` `second`の値)は以下。

```kotlin
class ExampleUnitTest {
    @Test
    fun android_util_pair() {
        val pair = android.util.Pair(1, 2)

        assert(pair.first == null)
        assert(pair.second == null)

    }

    @Test
    fun androidx_core_util_pair() {
        val pair = androidx.core.util.Pair(1, 2)

        assert(pair.first == 1)
        assert(pair.second == 2)

    }

    @Test
    fun kotlin_pair() {
        val pair = kotlin.Pair(1, 2)

        assert(pair.first == 1)
        assert(pair.second == 2)

    }
}
```


## なぜ?
**「Unitテストでは」**と強調しているところからも察することができるかもしれないですが、`android.util.Pair<F,S>(F first, S second)`を使ってインスタンスを作成しても`first`、`second`ともにnullになるのは**Unitテストのみ**です。
**実機で動かした場合は、ちゃんと`first`も`second`も渡した値になります。**

```kotlin
@Composable
fun Test(name: String, modifier: Modifier = Modifier) {
    val pair = android.util.Pair(1, 2)
    Log.d("test", "${pair.first} ${pair.second}")
}
```

```:コンソール
1 2
```

というのも`android.util.Pair`は`android.util.Log`などと同様に、実際の実装はAndroid端末の方にあるメソッドだからです。

### ちなみに①
`@RunWith(RobolectricTestRunner::class)`をつければ`android.util.Pair`のUnitテストでもOKです。(`Context`などと同じくです。)

```kotlin
@RunWith(RobolectricTestRunner::class)
class ExampleUnitTest{

    @Mock
    val pair = android.util.Pair.create(1, 2)

    @Test
    fun android_util_pair() {
        assert(pair.first == 1)
        assert(pair.second == 2)
    }
}

```


### ちなみに②

`android.util.Pair`の公式ドキュメント を見ると[`android.util.Pair<F, S> #create (F f,S s)`というstaticメソッド](https://developer.android.com/reference/android/util/Pair#create(A,%20B))もPairインスタンスを作るメソッドとしてあります。

こちらのメソッドは、`@RunWith(RobolectricTestRunner::class)`なしUnitテストだと**`RuntimeException`が発生** / `@RunWith(RobolectricTestRunner::class)`ありUnitテストだとちゃんと動きます。

```kotlin:@RunWith(RobolectricTestRunner::class)なし
class ExampleUnitTest{

    val pair = android.util.Pair.create(1, 2)

    @Test
    fun android_util_pair() {
        assert(pair.first == 1)
        assert(pair.second == 2)
    }
}
```

```:@RunWith(RobolectricTestRunner::class)なし結果
Method create in android.util.Pair not mocked. See https://developer.android.com/r/studio-ui/build/not-mocked for details.
java.lang.RuntimeException: Method create in android.util.Pair not mocked. See https://developer.android.com/r/studio-ui/build/not-mocked for details.
	at android.util.Pair.create(Pair.java)
	at com.example.myapplication.ExampleUnitTest.<init>(ExampleUnitTest.kt:18)
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)

(略)
```




```kotlin:@RunWith(RobolectricTestRunner::class)あり
@RunWith(RobolectricTestRunner::class)
class ExampleUnitTest{

    @Mock
    val pair = android.util.Pair.create(1, 2)

    @Test
    fun android_util_pair() {
        assert(pair.first == 1)
        assert(pair.second == 2)
    }
}
```
@RunWith(RobolectricTestRunner::class)あり結果 -> テストpass







# まとめ
プロダクトコードでは3つのPair全てで同じ動きになるものの、Unitテストを書くことを考えると`android.util.Pair`は使わないようにした方がよさそうです。

- mockのためのコードを書かなくていい・ビルド時間も削減
- そもそもmockに置き換えるということは正確性に若干欠ける
- テスト時に`android.util.Pair<F, S> #create (F f,S s)`の方は例外が発生するのでまだわかりやすいが、`android.util.Pair<F,S>(F first, S second)`コンストラクタの方は「値が想定と異なっていた」という意味での失敗しか起きないのでテストに失敗したときに原因が瞬時に察せないかもしれない。
    - (まさに私はこれで原因の切り分けにとても時間を使ってしまいました。。。nullではなく、例外発生にしてほしかったなぁというのが正直な気持ち。)