web-dev-qa-db-fra.com

moqueur Appels de réponse d'adaptation avec appel ne fonctionne pas

Je me moque de la réponse de l'APIService. Malheureusement, cela ne fonctionne pas, je dois renvoyer un appel mais je ne comprends pas comment. La question est de savoir comment renvoyer un objet Call. 

@RunWith(AndroidJUnit4::class)
class ApiServiceTest {

    @Test
    fun testSomething() {
        val apiService = ApiServiceMock()
        val call = apiService.getStep1User()
        val result = call.execute()
        Assert.assertEquals("SomeUserValue", result.body()!!.getResponse())
    }
}

Voici le service simulé:

class ApiServiceMock : ApiService {
    override fun getStep1User(): Call<UserResponse> {
        // How to return an object of type Call<UserResponse> ?
        val response = "{ \"Response\": \"SomeUserValue\" }"
        val gson = Gson().toJson(response)
        return Response.success(gson)
    }
}

Voici l'interface api:

interface ApiService {

    @GET("/booky/step1user")
    fun getStep1User(): Call<UserResponse>

    companion object {

        val interceptor = HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)
        val client = OkHttpClient.Builder()
                .addInterceptor(interceptor)
                .build()

        val retrofit = Retrofit.Builder()
                .baseUrl("http://jimclermonts.nl")
                .addConverterFactory(MoshiConverterFactory.create().asLenient())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .client(client)
                .build()
    }
}

build.gradle:

implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.squareup.retrofit2:converter-moshi:2.3.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.9.0'
implementation 'com.squareup.okhttp3:okhttp:3.9.0'
implementation "com.squareup.retrofit2:adapter-rxjava2:2.3.0"

implementation 'com.google.code.gson:gson:2.8.0'

testImplementation "org.mockito:mockito-core:2.12.0"
testImplementation "com.nhaarman:mockito-kotlin:1.5.0"
implementation 'org.mockito:mockito-Android:2.18.0'
11
Jim Clermonts

Ce que vous essayez de faire, c’est de tester la modification! Vous devez affirmer le comportement de votre application après avoir obtenu la réponse, et non pas indiquer quelle modification obtenir en réponse à la demande !! , une boîte de dialogue d'erreur doit apparaître.

Vous pouvez simuler la réponse à l'aide du serveur OkHTTPMock . Ajouter la dépendance dans votre fichier de module build.gradle:

testImplementation 'com.squareup.okhttp3:mockwebserver:lastVersion'

et ensuite dans votre fichier de test, vous pouvez simuler un serveur, une requête et une réponse ..__ ici un exemple:

MockWebServer server = new MockWebServer();
server.enqueue(new MockResponse().setBody("{ \"Response\": \"SomeUserValue\" }"));
// Start the server.
  server.start();

//and than load your request. Be Careful, they are executed in the order that you enqued them!

//Add your assertion (Succes response and error response)
//if you are working with MVP architecture, you can assert for the success case
//that method showData(data) is called using Mockito.
verify(myPresenter).showData(data);

Jetez un coup d’œil au officiel exemple de OkHttpMock

5
Fakher

Call est une interface, vous pouvez créer un objet qui l'implémente et le renvoyer depuis votre méthode moqueuse:

class ApiServiceMock : ApiService {
    override fun getStep1User(): Call<UserResponse> {
        return object: Call<SignedUserUi> {
            override fun enqueue(callback: Callback<UserResponse>?) {
            }

            override fun isExecuted(): Boolean {
                return false
            }

            override fun clone(): Call<UserResponse> {
                return this
            }

            override fun isCanceled(): Boolean {
                return false
            }

            override fun cancel() {

            }

            override fun request(): Request {
                return Request.Builder().build()
            }

            override fun execute(): Response<UserResponse> {
                // Create your mock data in here
                val response = "{ \"Response\": \"SomeUserValue\" }"
                val gson = Gson().toJson(response)
                return Response.success(UserResponse(gson))
            }

        }
    }
}

Si vous voulez avoir moins de passe-partout et pouvoir simuler des interfaces dans une seule ligne, je vous recommande de jeter un oeil à mockito pour kotlin.

Après l'avoir inclus dans votre projet, vous pourrez faire

val rawResponse = "{ \"Response\": \"SomeUserValue\" }"
val gson = Gson().toJson(rawResponse)
val response = Response.success(UserResponse(gson))

val mockCall = mock<Call<UserResponse>> {
    on { execute() } doReturn response
}

val mockApiService = mock<ApiService> {
    on { getStep1User() } doReturn mockCall
}
5
TpoM6oH

Vous pouvez utiliser RETURNS_DEEP_STUBS. Mais je ne sais pas comment ça marche à Kotlin.

mock = Mockito.mock(Api.class, RETURNS_DEEP_STUBS)
when(mock.getSomething().execute()).thenReturn(Response.success(...));
0
radeklos

Vous devez utiliser une classe d'assistance pour simuler des réponses.

class CallFake<T>(
    private val response: Response<T>) 
: Call<T> {

companion object {
    inline fun <reified T> buildSuccess(body: T): CallFake<T> {
        return CallFake(Response.success(body))
    }

    inline fun <reified T> buildHttpError(errorCode: Int, contentType: String, content: String): CallFake<T> {
        return CallFake(Response.error(errorCode, ResponseBody.create(MediaType.parse(contentType), content)))
    }
}

override fun execute(): Response<T> = response

override fun enqueue(callback: Callback<T>?) {}

override fun isExecuted(): Boolean = false

override fun clone(): Call<T> = this

override fun isCanceled(): Boolean = false

override fun cancel() {}

override fun request(): Request? = null 
}

ensuite, dans votre classe de test, vous devez utiliser la fonction lorsque, comme indiqué ci-dessous, vous indiquez quoi retourner lorsque vous appelez apiService.

@RunWith(MockitoJUnitRunner::class)
class ApiServiceTest {
@Mock
lateinit var apiService: ApiService

@Test
fun testSomething() {
    Mockito.`when`(apiService.getStep1User())
            .thenReturn(CallFake.buildSuccess(UserResponse("SomeUserValue")))

    val call = apiService.getStep1User()
    val response = call.execute()
    val userResponse = response.body() as UserResponse

    Assert.assertEquals("SomeUserValue", userResponse.userValue)
}
}
0
Daniel RL