Created
October 29, 2019 06:41
-
-
Save BenHenning/8c8bf8b7853526ab55b1b16643b43d94 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
interface ImageLoader { | |
fun load(imageUrl: String, target: CustomTarget<Bitmap>) | |
} | |
class GlideImageLoader @Inject constructor(...): ImageLoader { | |
override fun load(...) { | |
.. | |
} | |
} | |
// Note to Veena: we will inject ImageLoader rather than a Glide-specific one because then we can utilize Dagger to switch out | |
// the implementation in tests. This is done by having a production-only module bind the Glide version to ImageLoader: | |
@Module | |
abstract class GlideModule { | |
@Binds | |
abstract fun provideGlideImageLoader(impl: GlideImageLoader): ImageLoader | |
} | |
// Note to Veena: this module allows downstream code injecting ImageLoader to get GlideImageLoader by associating the types. | |
// E.g., the following code when built in production will actually get an instance of GlideImageLoader: | |
class Factory @Inject constructor(imageLoader: ImageLoader) { | |
... | |
} | |
// Note to Veena: However, we want to use a different ImageLoader instance at test time. This requires two things: | |
// 1. That we do not include GlideModule in tests (which means that ImageLoader must live in a module that does not | |
// automatically include modules in tests, like util). | |
// 2. We must provide the dependency in a test module (it's easy to verify that this is the case: trying to build | |
// the test without doing any extra work should fail with a Dagger error saying that a provider is missing for | |
// ImageLoader). | |
// We can provide a test dependency for ImageLoader like so: | |
class SomeTest { | |
@Inject | |
lateinit var mockImageLoader: ImageLoader // Inject the mock ImageLoader provided below. | |
// Prepares the ImageLoader for receiving the specified bitmap for the given URL. | |
private fun prepareImageLoaderForResponse(expectedUrl: String, bitmap: Bitmap) { | |
// Note to Veena: 'doAnswer', 'anyString', and 'any' are static Mockito imports. | |
doAnswer { invocation -> | |
// Note to Veena: this is called each time production code calls load() via the injected ImageLoader. | |
// The returned value here will be what load() returns, however that's void so we just return null. | |
// However, the invocation includes arguments like the target that we can use to provide the bitmap. | |
val customTarget: CustomTarget<Bitmap> = invocation.getArgument(1) | |
customTarget.onResourceReady(bitmap, /* transition= */ null) | |
return null | |
}.when(mockImageLoader).load(anyString(), any()) | |
} | |
@Module | |
class TestModule { | |
@Provides | |
fun provideImageLoader(): ImageLoader { | |
// Note to Veena: 'mock' here is a static Mockito import. | |
return mock(ImageLoader::class.java) // return a Mockito mock of ImageLoader | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment