From 6cf8557ca09aeead313a209208b9cb7d3993d29e Mon Sep 17 00:00:00 2001 From: Niek Haarman Date: Fri, 19 Aug 2016 22:04:41 +0200 Subject: [PATCH 1/9] Update README.md --- README.md | 105 +++++++++--------------------------------------------- 1 file changed, 17 insertions(+), 88 deletions(-) diff --git a/README.md b/README.md index 7dcfdb1e..b02f8ed3 100644 --- a/README.md +++ b/README.md @@ -17,96 +17,25 @@ dependencies { } ``` -## Examples +## Example -### Creating mock instances - -Due to Kotlin's [reified type parameters](https://kotlinlang.org/docs/reference/inline-functions.html#reified-type-parameters), if the type can be inferred, you don't have to specify it explicitly: - -**Java**: -```java -MyClass c = mock(Myclass.class); -c.doSomething(mock(MyOtherClass.class)); -``` - -**Kotlin**: -```kotlin -val c : MyClass = mock() -c.doSomething(mock()) -``` - -If the type can't be inferred, you can pass it like so: - -```kotlin -val d = mock() -``` - - -### Expecting any value - -Mockito's `any(Class)` often returns `null` for non-primitive classes. -In Kotlin, this can be a problem due to its [null-safety](https://kotlinlang.org/docs/reference/null-safety.html) feature. -This library creates non-null instances when necessary. -Again, if the type can be inferred, you don't have to specify it explicitely: - -**Java**: -```java -verify(myClass).doSomething(any(String.class)); -``` - -**Kotlin**: -```kotlin -verify(myClass).doSomething(any()); // Non-nullable parameter type is inferred -``` - -For generic arrays, use the `anyArray()` method: - -```kotlin -verify(myClass).setItems(anyArray()) -``` - -## Custom instance creators - -There are some cases where Mockito-Kotlin cannot create an instance of a class. -This can for instance be when a constructor has some specific preconditions -for its parameters. -You can _register_ `instance creators` to overcome this: - -```kotlin -MockitoKotlin.registerInstanceCreator { MyClass(5) } -``` - -Whenever MockitoKotlin needs to create an instance of `MyClass`, this function is called, -giving you ultimate control over how these instances are created. - -These instance creators work on a per-file basis: for each of your test files -you will need to register them again. - -### Argument Matchers - -Using higher-order functions, you can write very clear expectations about expected values. -For example: - -**Kotlin**: -```kotlin -verify(myClass).setItems(argThat{ size == 2 }) -``` - -### Argument Captors - -Argument Captors can be used to capture argument values for further assertions. -For example: +A test using Mockito-Kotlin typically looks like the following: ```kotlin -verify(myClass).setItems(capture { items -> - assertEquals(2, items.size) - assertEquals("test", items[0]) -}) +@Test +fun a(){ + /* Given */ + val mock = mock { + on { getText() } doReturn "text" + } + val classUnderTest = ClassUnderTest(mock) + + /* When */ + classUnderText.doAction() + + /* Then */ + verify(mock).doSomething(any()) +} ``` -### Convenience functions - -Most of Mockito's static functions are available as top-level functions. -That means, IDE's like IntelliJ can easily import and autocomplete them, saving you the hassle of manually importing them. - - +For more info and samples, see the [Wiki](https://github.com/nhaarman/mockito-kotlin/wiki). From 6110a908c68e0deab98f80143a75df6406fb5553 Mon Sep 17 00:00:00 2001 From: Niek Haarman Date: Fri, 9 Sep 2016 11:28:19 +0200 Subject: [PATCH 2/9] Update Mockito version to 2.1.0-beta.125 --- build.gradle | 3 ++- mockito-kotlin/build.gradle | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index cc7ac903..43d7b15e 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,6 @@ plugins { - id "com.jfrog.bintray" version "1.5" + id "com.jfrog.bintray" version "1.5" + id 'com.github.ben-manes.versions' version '0.13.0' } apply plugin: 'maven' apply plugin: 'maven-publish' diff --git a/mockito-kotlin/build.gradle b/mockito-kotlin/build.gradle index b3676bc1..8169f08f 100644 --- a/mockito-kotlin/build.gradle +++ b/mockito-kotlin/build.gradle @@ -20,7 +20,7 @@ repositories { dependencies { compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" - compile "org.mockito:mockito-core:2.0.99-beta" + compile "org.mockito:mockito-core:2.1.0-beta.125" /* Tests */ testCompile "junit:junit:4.12" From 58013d803355b0f92b8a552f037e45f0abddd3b9 Mon Sep 17 00:00:00 2001 From: Niek Haarman Date: Fri, 9 Sep 2016 11:30:05 +0200 Subject: [PATCH 3/9] Update dependencies --- build.gradle | 2 +- mockito-kotlin/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 43d7b15e..06fdf0f1 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id "com.jfrog.bintray" version "1.5" + id "com.jfrog.bintray" version "1.7.1" id 'com.github.ben-manes.versions' version '0.13.0' } apply plugin: 'maven' diff --git a/mockito-kotlin/build.gradle b/mockito-kotlin/build.gradle index 8169f08f..d35e7106 100644 --- a/mockito-kotlin/build.gradle +++ b/mockito-kotlin/build.gradle @@ -24,7 +24,7 @@ dependencies { /* Tests */ testCompile "junit:junit:4.12" - testCompile "com.nhaarman:expect.kt:0.5.1" + testCompile "com.nhaarman:expect.kt:0.6.0" } publishing { From 855c14ba580ff86e128d34cc880079c5999b60fc Mon Sep 17 00:00:00 2001 From: Niek Haarman Date: Fri, 9 Sep 2016 11:33:13 +0200 Subject: [PATCH 4/9] Update gradle wrapper to 3.0 --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 554f6fe7..46b1b27a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.14-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-3.0-all.zip From 18be9684c5264caea44261631c7db01dcc28163b Mon Sep 17 00:00:00 2001 From: Niek Haarman Date: Fri, 9 Sep 2016 11:20:02 +0200 Subject: [PATCH 5/9] Improve `easiestConstructor()` to sort by parameters size. --- .../nhaarman/mockito_kotlin/CreateInstance.kt | 20 +++++++------------ .../src/test/kotlin/CreateInstanceTest.kt | 13 ++++++++++++ 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/mockito-kotlin/src/main/kotlin/com/nhaarman/mockito_kotlin/CreateInstance.kt b/mockito-kotlin/src/main/kotlin/com/nhaarman/mockito_kotlin/CreateInstance.kt index bcbb064f..99206a8d 100644 --- a/mockito-kotlin/src/main/kotlin/com/nhaarman/mockito_kotlin/CreateInstance.kt +++ b/mockito-kotlin/src/main/kotlin/com/nhaarman/mockito_kotlin/CreateInstance.kt @@ -59,7 +59,7 @@ fun createInstance(kClass: KClass): T { kClass.isPrimitive() -> kClass.toDefaultPrimitiveValue() kClass.isEnum() -> kClass.java.enumConstants.first() kClass.isArray() -> kClass.toArrayInstance() - kClass.isClassObject() -> kClass.toClassObject() + kClass.isClassObject() -> kClass.toClassObject() else -> kClass.easiestConstructor().newInstance() } } @@ -68,20 +68,14 @@ fun createInstance(kClass: KClass): T { * Tries to find the easiest constructor which it can instantiate. */ private fun KClass.easiestConstructor(): KFunction { - return constructors.firstOrDefault( - { - it.parameters.filter { - it.type.toString().toLowerCase().contains("array") - }.isEmpty() - }, - { - constructors.sortedBy { it.parameters.size }.first() - } - ) + return constructors + .sortedBy { it.parameters.size } + .withoutArrayParameters() + .firstOrNull() ?: constructors.sortedBy { it.parameters.size }.first() } -private fun Collection.firstOrDefault(predicate: (T) -> Boolean, default: () -> T): T { - return firstOrNull(predicate) ?: default() +private fun List>.withoutArrayParameters() = filter { + it.parameters.filter { parameter -> parameter.type.toString().toLowerCase().contains("array") }.isEmpty() } @Suppress("SENSELESS_COMPARISON") diff --git a/mockito-kotlin/src/test/kotlin/CreateInstanceTest.kt b/mockito-kotlin/src/test/kotlin/CreateInstanceTest.kt index 75bddb18..a8207fcd 100644 --- a/mockito-kotlin/src/test/kotlin/CreateInstanceTest.kt +++ b/mockito-kotlin/src/test/kotlin/CreateInstanceTest.kt @@ -424,6 +424,15 @@ class CreateInstanceTest { } } + @Test + fun defaultEmptyConstructor_takesSimplestConstructor() { + /* When */ + val result = createInstance(WithDefaultEmptyConstructor::class) + + /* Then */ + expect(result).toNotBeNull() + } + private class PrivateClass private constructor(val data: String) class ClosedClass @@ -459,5 +468,9 @@ class CreateInstanceTest { } } + class WithDefaultEmptyConstructor() { + constructor(c: ForbiddenConstructor) : this() + } + enum class MyEnum { VALUE, ANOTHER_VALUE } } From 400b1cc38e83d6ddce5923b044cf9fd0220946df Mon Sep 17 00:00:00 2001 From: Niek Haarman Date: Fri, 9 Sep 2016 12:06:36 +0200 Subject: [PATCH 6/9] Deprecate methods that are deprecated in Mockito. --- .../com/nhaarman/mockito_kotlin/Mockito.kt | 25 ++++++++++++------- .../src/test/kotlin/MockitoKotlinTest.kt | 2 +- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/mockito-kotlin/src/main/kotlin/com/nhaarman/mockito_kotlin/Mockito.kt b/mockito-kotlin/src/main/kotlin/com/nhaarman/mockito_kotlin/Mockito.kt index d2be7efb..264d1c12 100644 --- a/mockito-kotlin/src/main/kotlin/com/nhaarman/mockito_kotlin/Mockito.kt +++ b/mockito-kotlin/src/main/kotlin/com/nhaarman/mockito_kotlin/Mockito.kt @@ -41,12 +41,7 @@ fun after(millis: Long) = Mockito.after(millis) inline fun any() = Mockito.any(T::class.java) ?: createInstance() inline fun anyArray(): Array = Mockito.any(Array::class.java) ?: arrayOf() -inline fun anyCollection(): Collection = Mockito.anyCollectionOf(T::class.java) -inline fun anyList(): List = Mockito.anyListOf(T::class.java) -inline fun anySet(): Set = Mockito.anySetOf(T::class.java) -inline fun anyMap(): Map = Mockito.anyMapOf(K::class.java, V::class.java) -inline fun anyVararg() = Mockito.anyVararg() ?: createInstance() - +inline fun anyVararg(): T = Mockito.any() ?: createInstance() inline fun argThat(noinline predicate: T.() -> Boolean) = Mockito.argThat { it -> (it as T).predicate() } ?: createInstance(T::class) fun atLeast(numInvocations: Int): VerificationMode = Mockito.atLeast(numInvocations)!! @@ -71,8 +66,8 @@ fun ignoreStubs(vararg mocks: Any): Array = Mockito.ignoreStubs(*mocks) fun inOrder(vararg mocks: Any): InOrder = Mockito.inOrder(*mocks)!! inline fun isA(): T? = Mockito.isA(T::class.java) -inline fun isNotNull(): T? = Mockito.isNotNull(T::class.java) -inline fun isNull(): T? = Mockito.isNull(T::class.java) +fun isNotNull(): T? = Mockito.isNotNull() +fun isNull(): T? = Mockito.isNull() inline fun mock(): T = Mockito.mock(T::class.java)!! inline fun mock(defaultAnswer: Answer): T = Mockito.mock(T::class.java, defaultAnswer)!! @@ -93,7 +88,7 @@ inline infix fun OngoingStubbing.doReturn(ts: List): OngoingSt fun mockingDetails(toInspect: Any): MockingDetails = Mockito.mockingDetails(toInspect)!! fun never(): VerificationMode = Mockito.never()!! -inline fun notNull(): T? = Mockito.notNull(T::class.java) +fun notNull(): T? = Mockito.notNull() fun only(): VerificationMode = Mockito.only()!! fun refEq(value: T, vararg excludeFields: String): T? = Mockito.refEq(value, *excludeFields) @@ -115,3 +110,15 @@ fun verifyZeroInteractions(vararg mocks: Any) = Mockito.verifyZeroInteractions(* fun whenever(methodCall: T): OngoingStubbing = Mockito.`when`(methodCall)!! fun withSettings(): MockSettings = Mockito.withSettings()!! + +@Deprecated("Use any() instead.", ReplaceWith("any()")) +inline fun anyCollection(): Collection = any() + +@Deprecated("Use any() instead.", ReplaceWith("any()")) +inline fun anyList(): List = any() + +@Deprecated("Use any() instead.", ReplaceWith("any()")) +inline fun anySet(): Set = any() + +@Deprecated("Use any() instead.", ReplaceWith("any()")) +inline fun anyMap(): Map = any() diff --git a/mockito-kotlin/src/test/kotlin/MockitoKotlinTest.kt b/mockito-kotlin/src/test/kotlin/MockitoKotlinTest.kt index 7f805651..3b5774f6 100644 --- a/mockito-kotlin/src/test/kotlin/MockitoKotlinTest.kt +++ b/mockito-kotlin/src/test/kotlin/MockitoKotlinTest.kt @@ -54,6 +54,6 @@ class MockitoKotlinTest { val result = createInstance() /* Then */ - expect(result).toNotBeReferentially(closed) + expect(result).toNotBeTheSameAs(closed) } } From 7dcebc913be37a66392d634f3558bcb698413230 Mon Sep 17 00:00:00 2001 From: Niek Haarman Date: Fri, 9 Sep 2016 12:21:27 +0200 Subject: [PATCH 7/9] Stop. Sending me. Emails. --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 150dc864..608fe0fc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,3 +14,6 @@ install: script: - ./gradlew test + +notifications: + email: false \ No newline at end of file From 9507a2077c76b71f7ecf2e0cd7bcb5ab6c19078d Mon Sep 17 00:00:00 2001 From: Niek Haarman Date: Fri, 9 Sep 2016 12:17:56 +0200 Subject: [PATCH 8/9] Make anyArray() accept nullable types. --- .../main/kotlin/com/nhaarman/mockito_kotlin/Mockito.kt | 2 +- mockito-kotlin/src/test/kotlin/Classes.kt | 1 + mockito-kotlin/src/test/kotlin/MockitoTest.kt | 8 ++++++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/mockito-kotlin/src/main/kotlin/com/nhaarman/mockito_kotlin/Mockito.kt b/mockito-kotlin/src/main/kotlin/com/nhaarman/mockito_kotlin/Mockito.kt index 264d1c12..3be50d90 100644 --- a/mockito-kotlin/src/main/kotlin/com/nhaarman/mockito_kotlin/Mockito.kt +++ b/mockito-kotlin/src/main/kotlin/com/nhaarman/mockito_kotlin/Mockito.kt @@ -40,7 +40,7 @@ import kotlin.reflect.KClass fun after(millis: Long) = Mockito.after(millis) inline fun any() = Mockito.any(T::class.java) ?: createInstance() -inline fun anyArray(): Array = Mockito.any(Array::class.java) ?: arrayOf() +inline fun anyArray(): Array = Mockito.any(Array::class.java) ?: arrayOf() inline fun anyVararg(): T = Mockito.any() ?: createInstance() inline fun argThat(noinline predicate: T.() -> Boolean) = Mockito.argThat { it -> (it as T).predicate() } ?: createInstance(T::class) diff --git a/mockito-kotlin/src/test/kotlin/Classes.kt b/mockito-kotlin/src/test/kotlin/Classes.kt index d494872c..2f066f36 100644 --- a/mockito-kotlin/src/test/kotlin/Classes.kt +++ b/mockito-kotlin/src/test/kotlin/Classes.kt @@ -43,6 +43,7 @@ interface Methods { fun intArray(i: IntArray) fun closed(c: Closed) fun closedArray(a: Array) + fun closedNullableArray(a: Array) fun closedCollection(c: Collection) fun closedList(c: List) fun closedStringMap(m: Map) diff --git a/mockito-kotlin/src/test/kotlin/MockitoTest.kt b/mockito-kotlin/src/test/kotlin/MockitoTest.kt index 7320dac3..e5c2eb22 100644 --- a/mockito-kotlin/src/test/kotlin/MockitoTest.kt +++ b/mockito-kotlin/src/test/kotlin/MockitoTest.kt @@ -64,6 +64,14 @@ class MockitoTest { } } + @Test + fun anyNullableClassArray() { + mock().apply { + closedNullableArray(arrayOf(Closed(), null)) + verify(this).closedNullableArray(anyArray()) + } + } + @Test fun anyCollectionOfClosed() { mock().apply { From 650e293e17989f9394a49683b99a9b7e292680d0 Mon Sep 17 00:00:00 2001 From: Niek Haarman Date: Fri, 9 Sep 2016 12:45:09 +0200 Subject: [PATCH 9/9] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b02f8ed3..e4422525 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ fun a(){ val classUnderTest = ClassUnderTest(mock) /* When */ - classUnderText.doAction() + classUnderTest.doAction() /* Then */ verify(mock).doSomething(any())