APIServiceの応答をモックしています。残念ながら機能していません。Callを返送する必要がありますが、その方法がわかりません。問題は、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())
}
}
模擬サービスは次のとおりです。
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)
}
}
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'
呼び出しはインターフェイスであり、それを実装するオブジェクトを作成して、モックメソッドから返すことができます。
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))
}
}
}
}
定型文を減らして、インターフェースを1行でモックできるようにする場合は、kotlinの mockito を確認することをお勧めします。
プロジェクトに含めると、次のことができるようになります。
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
}
あなたがやろうとしているのは、改造をテストすることです!応答を取得した後、アプリケーションの動作をアサートする必要があります。要求の応答として取得するレトロフィットをアサートする必要はありません。たとえば、エラー応答をアサートすると、エラーダイアログが表示されます。
OkHTTPMockサーバーを使用して応答をモックできます。 build.gradleモジュールファイルに依存関係を追加します。
testImplementation 'com.squareup.okhttp3:mockwebserver:lastVersion'
そして、テストファイルで、サーバー、リクエスト、およびレスポンスをモックできます。ここに例を示します:
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);
Officielを見てください 例 OkHttpMock
RETURNS_DEEP_STUBSを使用できます。しかし、Kotlinでどのように機能するかはわかりません。
mock = Mockito.mock(Api.class, RETURNS_DEEP_STUBS)
when(mock.getSomething().execute()).thenReturn(Response.success(...));
ヘルパークラスを使用して応答をモックする必要があります。
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
}
次に、テストクラスで、次に示すようにwhen関数を使用して、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)
}
}