Skip to content

Commit 5878bbe

Browse files
authored
Merge pull request #93 from nhaarman/release-0.8.0
Release 0.8.0
2 parents ea6e64c + d556691 commit 5878bbe

File tree

10 files changed

+345
-70
lines changed

10 files changed

+345
-70
lines changed

mockito-kotlin/build.gradle

Lines changed: 31 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,50 @@
11
apply plugin: 'kotlin'
2+
apply from: './publishing.gradle'
23

34
buildscript {
4-
ext.kotlin_version = '1.0.4'
5+
ext.kotlin_version = '1.0.4'
56

6-
repositories {
7-
mavenCentral()
8-
}
7+
repositories {
8+
mavenCentral()
9+
}
910

10-
dependencies {
11-
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
12-
}
11+
dependencies {
12+
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
13+
}
1314
}
1415

1516
repositories {
16-
mavenCentral()
17-
jcenter()
18-
}
19-
20-
dependencies {
21-
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
22-
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
23-
compile "org.mockito:mockito-core:2.1.0"
24-
25-
/* Tests */
26-
testCompile "junit:junit:4.12"
27-
testCompile "com.nhaarman:expect.kt:0.6.0"
17+
mavenCentral()
18+
jcenter()
2819
}
2920

30-
publishing {
31-
publications {
32-
MyPublication(MavenPublication) {
33-
from components.java
34-
artifact javadocJar
35-
artifact sourcesJar
36-
37-
groupId 'com.nhaarman'
38-
artifactId 'mockito-kotlin'
39-
version rootProject.ext.versionName
21+
sourceSets {
22+
testInlineMockito {
23+
compileClasspath += main.output + test.output
24+
runtimeClasspath += main.output + test.output
4025
}
41-
}
4226
}
4327

44-
bintray {
45-
user = hasProperty('bintray_user') ? bintray_user : System.getenv('BINTRAY_USER')
46-
key = hasProperty('bintray_key') ? bintray_key : System.getenv('BINTRAY_KEY')
47-
publications = ['MyPublication']
28+
configurations {
29+
testInlineMockitoCompile.extendsFrom testCompile
30+
testInlineMockitoRuntime.extendsFrom testRuntime
31+
}
4832

49-
pkg {
50-
repo = 'maven'
51-
name = "Mockito-Kotlin"
52-
desc = "Using Mockito with Kotlin"
33+
// define custom test task for running integration tests
34+
task testInlineMockito(type: Test) {
35+
testClassesDir = sourceSets.testInlineMockito.output.classesDir
36+
classpath = sourceSets.testInlineMockito.runtimeClasspath
37+
}
5338

54-
licenses = ['MIT']
55-
vcsUrl = 'https://github.com/bintray/gradle-bintray-plugin.git'
39+
test.dependsOn testInlineMockito
5640

57-
version {
58-
name = rootProject.ext.versionName
59-
desc = 'Using Mockito with Kotlin'
60-
vcsTag = rootProject.ext.versionName
61-
}
62-
}
63-
}
6441

65-
task javadocJar(type: Jar, dependsOn: javadoc) {
66-
classifier = 'javadoc'
67-
from 'build/docs/javadoc'
68-
}
42+
dependencies {
43+
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
44+
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
45+
compile "org.mockito:mockito-core:2.2.1"
6946

70-
task sourcesJar(type: Jar) {
71-
from sourceSets.main.allSource
72-
classifier = 'sources'
47+
/* Tests */
48+
testCompile "junit:junit:4.12"
49+
testCompile "com.nhaarman:expect.kt:0.6.0"
7350
}

mockito-kotlin/publishing.gradle

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
publishing {
2+
publications {
3+
MyPublication(MavenPublication) {
4+
from components.java
5+
artifact javadocJar
6+
artifact sourcesJar
7+
8+
groupId 'com.nhaarman'
9+
artifactId 'mockito-kotlin'
10+
version rootProject.ext.versionName
11+
}
12+
}
13+
}
14+
15+
bintray {
16+
user = hasProperty('bintray_user') ? bintray_user : System.getenv('BINTRAY_USER')
17+
key = hasProperty('bintray_key') ? bintray_key : System.getenv('BINTRAY_KEY')
18+
publications = ['MyPublication']
19+
20+
pkg {
21+
repo = 'maven'
22+
name = "Mockito-Kotlin"
23+
desc = "Using Mockito with Kotlin"
24+
25+
licenses = ['MIT']
26+
vcsUrl = 'https://github.com/bintray/gradle-bintray-plugin.git'
27+
28+
version {
29+
name = rootProject.ext.versionName
30+
desc = 'Using Mockito with Kotlin'
31+
vcsTag = rootProject.ext.versionName
32+
}
33+
}
34+
}
35+
36+
task javadocJar(type: Jar, dependsOn: javadoc) {
37+
classifier = 'javadoc'
38+
from 'build/docs/javadoc'
39+
}
40+
41+
task sourcesJar(type: Jar) {
42+
from sourceSets.main.allSource
43+
classifier = 'sources'
44+
}

mockito-kotlin/src/main/kotlin/com/nhaarman/mockito_kotlin/ArgumentCaptor.kt

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,32 @@
2626
package com.nhaarman.mockito_kotlin
2727

2828
import org.mockito.ArgumentCaptor
29+
import kotlin.reflect.KClass
30+
31+
inline fun <reified T : Any> argumentCaptor(): KArgumentCaptor<T> = KArgumentCaptor(ArgumentCaptor.forClass(T::class.java), T::class)
2932

30-
inline fun <reified T : Any> argumentCaptor() = ArgumentCaptor.forClass(T::class.java)
3133
inline fun <reified T : Any> capture(captor: ArgumentCaptor<T>): T = captor.capture() ?: createInstance<T>()
34+
35+
@Deprecated("Use captor.capture() instead.", ReplaceWith("captor.capture()"))
36+
inline fun <reified T : Any> capture(captor: KArgumentCaptor<T>): T = captor.capture()
37+
38+
class KArgumentCaptor<out T : Any>(private val captor: ArgumentCaptor<T>, private val tClass: KClass<T>) {
39+
40+
val value: T
41+
get() = captor.value
42+
43+
val allValues: List<T>
44+
get() = captor.allValues
45+
46+
fun capture(): T = captor.capture() ?: createInstance(tClass)
47+
}
48+
49+
/**
50+
* This method is deprecated because its behavior differs from the Java behavior.
51+
* Instead, use [argumentCaptor] in the traditional way, or use one of
52+
* [argThat], [argForWhich] or [check].
53+
*/
54+
@Deprecated("Use argumentCaptor() or argThat() instead.")
3255
inline fun <reified T : Any> capture(noinline consumer: (T) -> Unit): T {
3356
var times = 0
3457
return argThat { if (++times == 1) consumer.invoke(this); true }

mockito-kotlin/src/main/kotlin/com/nhaarman/mockito_kotlin/CreateInstance.kt

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import org.mockito.Answers
2929
import org.mockito.internal.creation.MockSettingsImpl
3030
import org.mockito.internal.creation.bytebuddy.MockAccess
3131
import org.mockito.internal.util.MockUtil
32+
import java.io.File
3233
import java.lang.reflect.InvocationTargetException
3334
import java.lang.reflect.Modifier
3435
import java.lang.reflect.ParameterizedType
@@ -40,12 +41,26 @@ import kotlin.reflect.defaultType
4041
import kotlin.reflect.jvm.isAccessible
4142
import kotlin.reflect.jvm.javaType
4243
import kotlin.reflect.jvm.jvmName
44+
import java.lang.reflect.Array as JavaArray
4345

4446
/**
4547
* A collection of functions that tries to create an instance of
4648
* classes to avoid NPE's when using Mockito with Kotlin.
4749
*/
4850

51+
/**
52+
* Checks whether the resource file to enable mocking of final classes is present.
53+
*/
54+
private var mockMakerInlineEnabled: Boolean? = null
55+
56+
private fun mockMakerInlineEnabled(jClass: Class<out Any>): Boolean {
57+
return mockMakerInlineEnabled ?:
58+
jClass.getResource("mockito-extensions/org.mockito.plugins.MockMaker")?.let {
59+
mockMakerInlineEnabled = File(it.file).readLines().filter { it == "mock-maker-inline" }.isNotEmpty()
60+
mockMakerInlineEnabled
61+
} ?: false
62+
}
63+
4964
inline fun <reified T> createArrayInstance() = arrayOf<T>()
5065

5166
inline fun <reified T : Any> createInstance() = createInstance(T::class)
@@ -81,7 +96,10 @@ private fun <T> List<KFunction<T>>.withoutArrayParameters() = filter {
8196
@Suppress("SENSELESS_COMPARISON")
8297
private fun KClass<*>.hasObjectInstance() = objectInstance != null
8398

84-
private fun KClass<*>.isMockable() = !Modifier.isFinal(java.modifiers)
99+
private fun KClass<*>.isMockable(): Boolean {
100+
return !Modifier.isFinal(java.modifiers) || mockMakerInlineEnabled(java)
101+
}
102+
85103
private fun KClass<*>.isEnum() = java.isEnum
86104
private fun KClass<*>.isArray() = java.isArray
87105
private fun KClass<*>.isClassObject() = jvmName.equals("java.lang.Class")
@@ -121,7 +139,10 @@ private fun <T : Any> KClass<T>.toArrayInstance(): T {
121139
"LongArray" -> longArrayOf()
122140
"DoubleArray" -> doubleArrayOf()
123141
"FloatArray" -> floatArrayOf()
124-
else -> throw UnsupportedOperationException("Cannot create a generic array for $simpleName. Use createArrayInstance() or anyArray() instead.")
142+
else -> {
143+
val name = java.name.drop(2).dropLast(1)
144+
return JavaArray.newInstance(Class.forName(name), 0) as T
145+
}
125146
} as T
126147
}
127148

@@ -168,10 +189,10 @@ private fun <T : Any> KType.createNullableInstance(): T? {
168189
* Creates a mock instance of given class, without modifying or checking any internal Mockito state.
169190
*/
170191
@Suppress("UNCHECKED_CAST")
171-
private fun <T> Class<T>.uncheckedMock(): T {
192+
fun <T> Class<T>.uncheckedMock(): T {
172193
val impl = MockSettingsImpl<T>().defaultAnswer(Answers.RETURNS_DEFAULTS) as MockSettingsImpl<T>
173194
val creationSettings = impl.confirm(this)
174195
return MockUtil.createMock(creationSettings).apply {
175-
(this as MockAccess).mockitoInterceptor = null
196+
(this as? MockAccess)?.mockitoInterceptor = null
176197
}
177198
}

mockito-kotlin/src/main/kotlin/com/nhaarman/mockito_kotlin/Mockito.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ inline fun <reified T : Any?> anyArray(): Array<T> = Mockito.any(Array<T>::class
5353

5454
inline fun <reified T : Any> argThat(noinline predicate: T.() -> Boolean) = Mockito.argThat<T> { it -> (it as T).predicate() } ?: createInstance(T::class)
5555
inline fun <reified T : Any> argForWhich(noinline predicate: T.() -> Boolean) = argThat(predicate)
56+
inline fun <reified T : Any> check(noinline predicate: (T) -> Unit) = Mockito.argThat<T> { it -> predicate(it); true } ?: createInstance(T::class)
5657

5758
fun atLeast(numInvocations: Int): VerificationMode = Mockito.atLeast(numInvocations)!!
5859
fun atLeastOnce(): VerificationMode = Mockito.atLeastOnce()!!
@@ -99,6 +100,11 @@ infix fun <T> OngoingStubbing<T>.doReturn(t: T): OngoingStubbing<T> = thenReturn
99100
fun <T> OngoingStubbing<T>.doReturn(t: T, vararg ts: T): OngoingStubbing<T> = thenReturn(t, *ts)
100101
inline infix fun <reified T> OngoingStubbing<T>.doReturn(ts: List<T>): OngoingStubbing<T> = thenReturn(ts[0], *ts.drop(1).toTypedArray())
101102

103+
infix fun <T> OngoingStubbing<T>.doThrow(t: Throwable): OngoingStubbing<T> = thenThrow(t)
104+
fun <T> OngoingStubbing<T>.doThrow(t: Throwable, vararg ts: Throwable): OngoingStubbing<T> = thenThrow(t, *ts)
105+
infix fun <T> OngoingStubbing<T>.doThrow(t: KClass<out Throwable>): OngoingStubbing<T> = thenThrow(t.java)
106+
fun <T> OngoingStubbing<T>.doThrow(t: KClass<out Throwable>, vararg ts: KClass<out Throwable>): OngoingStubbing<T> = thenThrow(t.java, *ts.map { it.java }.toTypedArray())
107+
102108
fun mockingDetails(toInspect: Any): MockingDetails = Mockito.mockingDetails(toInspect)!!
103109
fun never(): VerificationMode = Mockito.never()!!
104110
fun <T : Any> notNull(): T? = Mockito.notNull()
Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,39 @@
1+
import com.nhaarman.expect.expect
12
import com.nhaarman.mockito_kotlin.argumentCaptor
23
import com.nhaarman.mockito_kotlin.mock
4+
import com.nhaarman.mockito_kotlin.times
35
import com.nhaarman.mockito_kotlin.verify
4-
import com.nhaarman.expect.expect
5-
import com.nhaarman.mockito_kotlin.capture
66
import org.junit.Test
77
import java.util.*
88

99
class ArgumentCaptorTest {
1010

1111
@Test
1212
fun explicitCaptor() {
13+
/* Given */
1314
val date: Date = mock()
14-
val time = argumentCaptor<Long>()
1515

16+
/* When */
1617
date.time = 5L
1718

18-
verify(date).time = capture(time)
19-
expect(time.value).toBe(5L)
19+
/* Then */
20+
val captor = argumentCaptor<Long>()
21+
verify(date).time = captor.capture()
22+
expect(captor.value).toBe(5L)
2023
}
2124

2225
@Test
23-
fun implicitCaptor() {
26+
fun argumentCaptor_multipleValues() {
27+
/* Given */
2428
val date: Date = mock()
29+
30+
/* When */
2531
date.time = 5L
32+
date.time = 7L
2633

27-
verify(date).time = capture {
28-
expect(it).toBe(5L)
29-
}
34+
/* Then */
35+
val captor = argumentCaptor<Long>()
36+
verify(date, times(2)).time = captor.capture()
37+
expect(captor.allValues).toBe(listOf(5, 7))
3038
}
3139
}

mockito-kotlin/src/test/kotlin/CreateInstanceTest.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,10 +159,13 @@ class CreateInstanceTest {
159159
expect(result).toNotBeNull()
160160
}
161161

162-
@Test(expected = UnsupportedOperationException::class)
162+
@Test
163163
fun classArray_usingAny() {
164164
/* When */
165-
createInstance<Array<Open>>()
165+
val result = createInstance<Array<Open>>()
166+
167+
/* Then */
168+
expect(result).toBeInstanceOf<Array<Open>>()
166169
}
167170

168171
@Test

0 commit comments

Comments
 (0)