android - Android单元测试改造失败

标签 android unit-testing kotlin retrofit2 kotlin-coroutines

我正在为使用更新服务的AuthenticationDataSource类编写单元测试,因此我使用MockWebServer来模拟响应,这是运行测试时的输出:

java.lang.IllegalStateException: This job has not completed yet

这是我的测试类AuthenticationDataSourceTest:
@ExperimentalCoroutinesApi
class AuthenticationDataSourceTest {

    private val mockWebServer: MockWebServer = MockWebServer()
    private lateinit var apiService: ApiService
    private lateinit var SUT: AuthenticationDataSource

    @Before
    fun setUp() {
        mockWebServer.start()
        apiService =
            Retrofit.Builder()
                .baseUrl(mockWebServer.url("/"))
                .addConverterFactory(MoshiConverterFactory.create())
                .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke())
                .build()
                .create(ApiService::class.java)

        val mockApolloClient = mockk<ApolloClient>()
        SUT = AuthenticationDataSource(apiService, mockApolloClient)
    }

    @After
    fun tearDown() {
        mockWebServer.shutdown()
    }

    @Test
    fun retrieveAccessToken_returnsAccessToken() = runBlockingTest {
        // Given
        val response = MockResponse()
            .setResponseCode(HttpURLConnection.HTTP_OK)
            .setBody(FileUtils.readTestResourceFile("access_token_success.json"))
        mockWebServer.enqueue(response)

        // When
        val accessToken = SUT.getAccessToken("", "", "")

        // Then
        assertThat(accessToken).isNotNull()
    }
}

这是我的AuthenticationDataSource类:
class AuthenticationDataSource @Inject constructor(
    private val retrofitService: ApiService,
    private val apolloClient: ApolloClient
) {

    suspend fun getAccessToken(
        clientId: String,
        clientSecret: String,
        code: String
    ): Result<Token> {
        return try {
            val tokenModel = retrofitService.getAccessToken(
                clientId = clientId,
                clientSecret = clientSecret,
                redirectUri = Constant.REDIRECT_URI,
                grantType = "authorization_code",
                code = code
            )
            Result.Success(tokenModel)
        } catch (throwable: Throwable) {
            Timber.e(throwable)
            Result.Error(throwable)
        }
    }
}

最后是我的ApiService:
interface ApiService {
    @POST("/v2/oauth/token")
    suspend fun getAccessToken(
        @Query("client_id") clientId: String,
        @Query("client_secret") clientSecret: String,
        @Query("redirect_uri") redirectUri: String,
        @Query("grant_type") grantType: String,
        @Query("code") code: String
    ): Token
}

任何帮助都非常感谢,谢谢。

最佳答案

使用runBlocking代替runBlockingTest https://github.com/square/retrofit/issues/3330

关于android - Android单元测试改造失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61996654/

相关文章:

java - 使用 AssertJ 断言列表中的单个对象

python - python-3.3 的模拟工具

android - 如何在私有(private)路径中使用 DownloadManager 保存文件?

android - fragment 中的 AdMob 横幅

android - 创建具有重复位图背景的圆角按钮的最佳方法。

java - 单元测试中@Nonnull 注释的 Intellij IDEA 警告

Android Studio 在获取文档时挂起

java - "Object"不是这个 Realm 的架构的一部分

android - 代码的位置,以便 'SharedPreferences' 与 'onOptionsItemSelected' 一起使用

android - 无法从本地日期转换为伦敦日期对象