diff --git a/mocks/build.gradle b/mocks/build.gradle index 65fc4b5bc2..7cb225f5db 100644 --- a/mocks/build.gradle +++ b/mocks/build.gradle @@ -4,6 +4,7 @@ dependencies { implementation project(':library') implementation "androidx.annotation:annotation:${ANDROID_X_VERSION}" implementation "com.google.guava:guava:${GUAVA_VERSION}" + implementation "org.mockito:mockito-core:${MOCKITO_VERSION}" } android { diff --git a/mocks/lint.xml b/mocks/lint.xml new file mode 100644 index 0000000000..98c3d60d7b --- /dev/null +++ b/mocks/lint.xml @@ -0,0 +1,4 @@ + + + + diff --git a/mocks/src/main/java/com/bumptech/glide/mocks/AnswerSelf.java b/mocks/src/main/java/com/bumptech/glide/mocks/AnswerSelf.java new file mode 100644 index 0000000000..0dc9c3656c --- /dev/null +++ b/mocks/src/main/java/com/bumptech/glide/mocks/AnswerSelf.java @@ -0,0 +1,26 @@ +package com.bumptech.glide.mocks; + +import static org.mockito.Mockito.RETURNS_DEFAULTS; + +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +/** + * Useful default when mocking {@link com.bumptech.glide.request.RequestOptions} or {@link + * com.bumptech.glide.RequestBuilder}. + * + * @param The type of the options and/or builder. + */ +final class AnswerSelf implements Answer { + + @SuppressWarnings("unchecked") + @Override + public T answer(InvocationOnMock invocation) throws Throwable { + Object mock = invocation.getMock(); + if (invocation.getMethod().getReturnType().isInstance(mock)) { + return (T) mock; + } else { + return (T) RETURNS_DEFAULTS.answer(invocation); + } + } +} diff --git a/mocks/src/main/java/com/bumptech/glide/mocks/MockGlideBuilders.java b/mocks/src/main/java/com/bumptech/glide/mocks/MockGlideBuilders.java new file mode 100644 index 0000000000..37e1eae5fc --- /dev/null +++ b/mocks/src/main/java/com/bumptech/glide/mocks/MockGlideBuilders.java @@ -0,0 +1,41 @@ +package com.bumptech.glide.mocks; + +import static org.mockito.Mockito.mock; + +import com.bumptech.glide.RequestBuilder; +import com.bumptech.glide.request.RequestOptions; + +/** + * Mocks for various builder patterns in Glide to make testing easier. + * + *

All methods share the same behavior. Any method on the builder that returns the builder itself + * will default to returning the mock rather than null. Any method on the builder that returns + * anything other than the builder will return Mockito's standard default return value. + */ +public final class MockGlideBuilders { + + private MockGlideBuilders() {} + + /** Creates a new {@link RequestBuilder} instance with a matching resource type. */ + @SuppressWarnings("unchecked") + public static RequestBuilder mockRequestBuilder() { + return (RequestBuilder) mockGlideRequest(RequestBuilder.class); + } + + /** Creates a new instance of a generated {@code GlideRequest} class for an application. */ + // The suppressions allow callers to get a typed class without warnings in their test code. + @SuppressWarnings({"unchecked", "TypeParameterUnusedInFormals"}) + public static > Y mockGlideRequest(Class glideRequest) { + return (Y) mock(glideRequest, new AnswerSelf()); + } + + /** Creates a new {@link RequestOptions} instance. */ + public static RequestOptions mockRequestOptions() { + return mockGlideOptions(RequestOptions.class); + } + + /** Creates a new instance of a generated {@code GlideOptions} class for an application. */ + public static T mockGlideOptions(Class glideOptionsClass) { + return mock(glideOptionsClass, new AnswerSelf()); + } +}