Last active
November 6, 2019 06:23
-
-
Save parthdave93/a3ee2241cd118fe0eb5990bbfb904301 to your computer and use it in GitHub Desktop.
Mockito mock custom made mock class
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
apply plugin: 'com.android.application' | |
apply plugin: 'kotlin-android' | |
apply plugin: 'kotlin-android-extensions' | |
android { | |
compileSdkVersion 29 | |
buildToolsVersion "29.0.2" | |
defaultConfig { | |
applicationId "com.parthdave93" | |
minSdkVersion 19 | |
targetSdkVersion 29 | |
versionCode 1 | |
versionName "1.0" | |
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" | |
} | |
buildTypes { | |
release { | |
minifyEnabled false | |
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' | |
} | |
} | |
} | |
dependencies { | |
implementation fileTree(dir: 'libs', include: ['*.jar']) | |
implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" | |
implementation 'androidx.appcompat:appcompat:1.0.2' | |
implementation 'androidx.core:core-ktx:1.0.2' | |
implementation 'androidx.constraintlayout:constraintlayout:1.1.3' | |
testImplementation 'junit:junit:4.12' | |
androidTestImplementation 'androidx.test.ext:junit:1.1.0' | |
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' | |
implementation 'io.reactivex.rxjava2:rxandroid:2.1.0' | |
testImplementation 'org.mockito:mockito-core:1.10.19' | |
testImplementation 'org.mockito:mockito-all:1.10.19' | |
} |
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
import com.com.parthdave93.mock.Foo | |
import com.com.parthdave93.mock.FooInterface | |
import com.com.parthdave93.ownmockingmodule.MockDave | |
import org.mockito.Mockito | |
object CustomMockitoTestSuit { | |
@JvmStatic | |
fun main(args: Array<String>) { | |
// java.lang.reflect.Proxy | |
println("# CustomMockProxy By Parth Dave") | |
val fooInterfaceMock = CustomMockProxy.mock(FooInterface::class.java) | |
CustomMockProxy.`when`(fooInterfaceMock.foo()).thenReturn("Foo Fighters!") | |
println(fooInterfaceMock.foo()) | |
CustomMockProxy.`when`(fooInterfaceMock.echo("echo")).thenReturn("echo") | |
println(fooInterfaceMock.echo("echo")) | |
CustomMockProxy.`when`(fooInterfaceMock.echo("hello")).thenReturn("world") | |
println(fooInterfaceMock.echo("hello")) | |
println() | |
} | |
} |
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
import java.lang.reflect.InvocationHandler | |
import java.lang.reflect.Method | |
import java.lang.reflect.Proxy | |
import java.util.ArrayList | |
import java.util.Arrays | |
class CustomMockProxy { | |
companion object { | |
private var lastMockInvocationHandler: MockInvocationHandler? = null | |
/** | |
* Creates a mock based on a class. | |
* | |
* @param clazz the class of the mock | |
* @param <T> the type of the mock | |
* @return the mock object | |
</T> */ | |
fun <T> mock(clazz: Class<T>): T { | |
val invocationHandler = MockInvocationHandler() | |
return Proxy.newProxyInstance( | |
MockProxy::class.java.classLoader, | |
arrayOf<Class<*>>(clazz), | |
invocationHandler | |
) as T | |
} | |
/** | |
* This class is just needed to ERHALTEN the type information. So that we | |
* have the type information for the When::thenReturn method. | |
* | |
* @param obj the value which we doesn't need. | |
* @param <T> the type of the return value | |
* @return an instance of When with the correct type information | |
</T> */ | |
fun <T> `when`(obj: T?): When { | |
return When() | |
} | |
} | |
class When{ | |
/** | |
* Sets the return value for the last method call. | |
* | |
* @param retObj the return value | |
*/ | |
fun thenReturn(retObj: Any) { | |
lastMockInvocationHandler!!.setRetObj(retObj) | |
} | |
} | |
private class MockInvocationHandler : InvocationHandler { | |
private var lastMethod: Method? = null | |
private var lastArgs: Array<Any>? = null | |
private val dataHolders = ArrayList<DataHolder>() | |
/** | |
* Intercepts the method call and decides what value will be returned. | |
*/ | |
@Throws(Throwable::class) | |
override fun invoke(proxy: Any?, method: Method?, args: Array<Any>?): Any? { | |
lastMockInvocationHandler = this | |
lastMethod = method | |
lastArgs = args | |
// checks if the method was already called with the given arguments | |
for (dataHolder in dataHolders) { | |
if (dataHolder.method == method && Arrays.deepEquals(dataHolder.args, args)) { | |
// if so than return the stored value | |
return dataHolder.retObj | |
} | |
} | |
// otherwise return null | |
return null | |
} | |
/** | |
* Adds the return value for the last called method with the last given arguments. | |
* | |
* @param retObj the return value | |
*/ | |
fun setRetObj(retObj: Any?) { | |
var isFound = false | |
for (dataHolder in dataHolders) { | |
if (dataHolder.method == lastMethod && Arrays.deepEquals( | |
dataHolder.args, | |
lastArgs | |
) | |
) { | |
dataHolder.retObj = retObj | |
isFound = true | |
} | |
} | |
if (!isFound) | |
dataHolders.add(DataHolder(lastMethod, lastArgs, retObj)) | |
} | |
/** | |
* Stores the method with it's arguments and the return value. | |
*/ | |
inner class DataHolder( | |
val method: Method?, | |
val args: Array<Any>?, | |
var retObj: Any? | |
) | |
} | |
} |
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
# MockProxy | |
Foo Fighters! | |
echo | |
world |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment