Android单元测试改造失败

时间:2020-05-25 06:03:39

标签: 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
}

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

1 个答案:

答案 0 :(得分:2)

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