I'm working on an android library project, where I need to download an PNG image from a REST service, transform it into a Bitmap
and return it to the app(s) using this library. So, we have a REST webservice that returns the bytes of a png image. We're calling this service using Retrofit
with rxJava
. In my code below accessRemoteComm.getImage()
does the loading and transformation from ResponseBody
to Bitmap
inside a .map
on the Observable. The image loads fine in the application. I now want to unit test that method, but I'm having a hard time getting MockWebServer
to deliver the image in the first place. The OnError
is called constantly with:
java.lang.RuntimeException: Method decodeStream in android.graphics.BitmapFactory not mocked. See http://g.co/androidstudio/not-mocked for details.
This is what I have so far:
Retrofit interface:
@GET("webapi/user/{ID}/image")
Observable<ResponseBody> getVehicleImage(
@Path("ID") @NonNull final String id,
@Query("width") @NonNull final int width,
@Query("height") @NonNull final int height,
@Query("view") @NonNull final ImageView view
);
getImage() Method:
public Observable<Bitmap> getVehicleImage(@NonNull String id, @NonNull Integer width, @NonNull Integer height, @NonNull ImageView view) {
return service.getImage(id, width, height, view).map(new Func1<ResponseBody, Bitmap>() {
@Override
public Bitmap call(ResponseBody responseBody) {
BufferedInputStream isr = new BufferedInputStream(responseBody.byteStream());
return BitmapFactory.decodeStream(isr);
}
});
}
My test method:
@Test
public void testGetVehicleImage() throws Exception {
String path = basePathForImages + "vehicleTestImage.png";
Source pngSource = Okio.source(new File(path));
BufferedSource bufferedSrc = Okio.buffer(pngSource);
server.enqueue(new MockResponse()
.setResponseCode(200)
.setHeader("Content-Type", "image/png")
.setBody(bufferedSrc.buffer()));
Subscriber<Bitmap> subscriber = new Subscriber<Bitmap>() {
@Override
public void onCompleted() {
Log.d("OnComplete");
}
@Override
public void onError(Throwable e) {
Log.d(e.toString());
//java.lang.RuntimeException:
//Method decodeStream in android.graphics.BitmapFactory not mocked.
}
@Override
public void onNext(Bitmap bitmap) {
Log.d("Yeeee");
}
};
Observable<Bitmap> observable = accessRemoteCommVehicle.getVehicleImage("abc", 0, 0, VehicleImageView.FRONT);
observable.toBlocking().subscribe(subscriber);
}
I'm pretty sure, that I don't setup the bufferedSource
correctly. But I cannot find any resources on SO or the web that shows the usage of the MockResponse
with a Buffer
as body.
And this is the part, where any help is appreciated. How do I set this up correctly?
Btw. If you have any other suggestion on how to test this, please let me know!
Thank you!
The recommended way of testing your code that uses OkHttp is to utilise their MockWebServer utility. This allows the execution of tests in a realistic operation with full control of responses being passed to the client.
I am currently using this with MockWebServer and seems to work, but could use some mileage. Would be beneficial to the community if you try it and feed back your result.
import okio.Buffer;
private final static String TAG = "MYCLASS";
public static String extPathToPngFile = Environment.getExternalStorageDirectory().getPath() + "/some-icon.png";
Buffer responseBody = getBinaryFileAsBuffer(extPathToPngFile);
... context removed for brevity ...
new MockResponse().setResponseCode(200).addHeader("Content-Type:image/png").setBody(responseBody);
//Buffer wrap a binary file to return with a mock.
public static Buffer getBinaryFileAsBuffer(String path) throws IOException {
File file = new File(path);
byte[] fileData = FileUtils.readFileToByteArray(file);
Buffer buf = new Buffer();
buf.write(fileData);
Log.d(TAG, "BUFFER SIZE FOR "+path+" IS:" + buf.size());
return buf;
}
android.graphics.BitmapFactory
is part of Android SDK, so it's available on device/emulator only. In your case your are running unit tests on your host machine (where your code gets compiled), Android SDK classes are not available in that environment. Judging by the error you use Mockito to mock calls to SDK but decodeStream method is not mocked.
There a couple of ways you could approach this:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With