From 76be5d0a02865e3f8a1c018351f999b725ce7db1 Mon Sep 17 00:00:00 2001 From: Anton Keks Date: Wed, 17 Feb 2016 00:58:30 +0200 Subject: [PATCH 1/8] add more missing Mockito methods, especially to be used with spies --- .../kotlin/com/nhaarman/mockito_kotlin/Mockito.kt | 12 ++++++++++++ 1 file changed, 12 insertions(+) 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 3d093230..f0643dbc 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 @@ -30,6 +30,7 @@ import org.mockito.verification.VerificationMode import kotlin.reflect.KClass inline fun mock() = Mockito.mock(T::class.java) +inline fun mock(defaultAnswer: Answer) = Mockito.mock(T::class.java, defaultAnswer) fun spy(value: T) = Mockito.spy(value) fun whenever(methodCall: T) = Mockito.`when`(methodCall) @@ -40,6 +41,17 @@ fun reset(mock: T) = Mockito.reset(mock) fun inOrder(vararg value: Any) = Mockito.inOrder(*value) fun never() = Mockito.never() +fun times(numInvocations: Int) = Mockito.times(numInvocations) +fun atLeast(numInvocations: Int) = Mockito.atLeast(numInvocations) +fun atLeastOnce() = Mockito.atLeastOnce() + +fun doReturn(value: Any) = Mockito.doReturn(value) +fun doThrow(throwable: Throwable) = Mockito.doThrow(throwable) +fun doAnswer(answer: Answer) = Mockito.doAnswer(answer) +fun doCallRealMethod() = Mockito.doCallRealMethod() +fun doNothing() = Mockito.doNothing() + +fun Stubber.whenever(mock: T) = `when`(mock) inline fun eq(value: T) = Mockito.eq(value) ?: createInstance() inline fun anyArray(): Array = Mockito.any(Array::class.java) ?: arrayOf() From 334d4716d018b1dcae64f6a7feaae25aaa1ad86e Mon Sep 17 00:00:00 2001 From: Anton Keks Date: Wed, 17 Feb 2016 01:05:25 +0200 Subject: [PATCH 2/8] add missing imports --- .../src/main/kotlin/com/nhaarman/mockito_kotlin/Mockito.kt | 2 ++ 1 file changed, 2 insertions(+) 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 f0643dbc..144d5a0c 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 @@ -26,6 +26,8 @@ package com.nhaarman.mockito_kotlin import org.mockito.Mockito +import org.mockito.stubbing.Answer +import org.mockito.stubbing.Stubber import org.mockito.verification.VerificationMode import kotlin.reflect.KClass From 0efd093b42035b381e8c5b75e7204dd19f87e5e5 Mon Sep 17 00:00:00 2001 From: Niek Haarman Date: Thu, 18 Feb 2016 13:37:27 +0100 Subject: [PATCH 3/8] Added PR template --- .github/PULL_REQUEST_TEMPLATE.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .github/PULL_REQUEST_TEMPLATE.md diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..fa6cbc39 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,5 @@ +Thank you for submitting a pull request! But first: + + - [ ] Can you back your code up with tests? + - [ ] Keep your commits clean: [squash your commits if necessary](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History). + - [ ] Make sure you're targeting the `dev` branch with the PR. From f6f142ade26f7586028ef8a82a2d1f7b1d7b14b7 Mon Sep 17 00:00:00 2001 From: Anton Keks Date: Fri, 19 Feb 2016 13:20:51 +0200 Subject: [PATCH 4/8] add spy stubbing tests --- mockito-kotlin/src/test/kotlin/SpyTest.kt | 33 ++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/mockito-kotlin/src/test/kotlin/SpyTest.kt b/mockito-kotlin/src/test/kotlin/SpyTest.kt index 860abf98..e09ee251 100644 --- a/mockito-kotlin/src/test/kotlin/SpyTest.kt +++ b/mockito-kotlin/src/test/kotlin/SpyTest.kt @@ -24,11 +24,12 @@ */ import com.nhaarman.expect.expect -import com.nhaarman.mockito_kotlin.spy +import com.nhaarman.mockito_kotlin.* import org.junit.After import org.junit.Test import org.mockito.Mockito import org.mockito.exceptions.base.MockitoException +import java.util.* class SpyTest { @@ -66,6 +67,36 @@ class SpyTest { spy(closedClassInstance) } + @Test + fun doReturnWithSpy() { + val date = spy(Date()) + doReturn(123L).whenever(date).time + expect(date.time).toBe(123L) + } + + @Test + fun doNothingWithSpy() { + val date = spy(Date(0)) + doNothing().whenever(date).time = 5L + date.time = 5L; + expect(date.time).toBe(0L) + } + + @Test(expected = IllegalArgumentException::class) + fun doThrowWithSpy() { + val date = spy(Date(0)) + doThrow(IllegalArgumentException()).whenever(date).time + date.time + } + + @Test + fun doCallRealMethodWithSpy() { + val date = spy(Date(0)) + doReturn(123L).whenever(date).time + doCallRealMethod().whenever(date).time + expect(date.time).toBe(0L) + } + private interface MyInterface private open class MyClass : MyInterface private class ClosedClass From 1262c198418fb07d1cd5713104f7c756885b7b25 Mon Sep 17 00:00:00 2001 From: Anton Keks Date: Fri, 19 Feb 2016 13:25:42 +0200 Subject: [PATCH 5/8] add deep stubs test --- mockito-kotlin/src/test/kotlin/MockTest.kt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/mockito-kotlin/src/test/kotlin/MockTest.kt b/mockito-kotlin/src/test/kotlin/MockTest.kt index 0ba72853..e46f3db3 100644 --- a/mockito-kotlin/src/test/kotlin/MockTest.kt +++ b/mockito-kotlin/src/test/kotlin/MockTest.kt @@ -25,8 +25,11 @@ import com.nhaarman.expect.expect import com.nhaarman.mockito_kotlin.mock +import com.nhaarman.mockito_kotlin.whenever import org.junit.Test +import org.mockito.Mockito.RETURNS_DEEP_STUBS import org.mockito.exceptions.base.MockitoException +import java.util.* class MockTest { @@ -82,6 +85,13 @@ class MockTest { mock() } + @Test + fun deepStubs() { + val cal: Calendar = mock(RETURNS_DEEP_STUBS) + whenever(cal.time.time).thenReturn(123L) + expect(cal.time.time).toBe(123L) + } + private interface MyInterface private open class MyClass private class ClosedClass From 66e3be5b74d7ddf3d58f0142de3aa7bd26f955d5 Mon Sep 17 00:00:00 2001 From: Anton Keks Date: Fri, 19 Feb 2016 13:43:48 +0200 Subject: [PATCH 6/8] add simplified ArgumentCaptor support --- .../com/nhaarman/mockito_kotlin/Mockito.kt | 4 ++++ .../src/test/kotlin/ArgumentCaptorTest.kt | 20 +++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 mockito-kotlin/src/test/kotlin/ArgumentCaptorTest.kt 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 144d5a0c..4d8a7d4a 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 @@ -25,6 +25,7 @@ package com.nhaarman.mockito_kotlin +import org.mockito.ArgumentCaptor import org.mockito.Mockito import org.mockito.stubbing.Answer import org.mockito.stubbing.Stubber @@ -55,6 +56,9 @@ fun doNothing() = Mockito.doNothing() fun Stubber.whenever(mock: T) = `when`(mock) +inline fun argumentCaptor() = ArgumentCaptor.forClass(T::class.java) +inline fun capture(captor: ArgumentCaptor): T = captor.capture() ?: createInstance() + inline fun eq(value: T) = Mockito.eq(value) ?: createInstance() inline fun anyArray(): Array = Mockito.any(Array::class.java) ?: arrayOf() inline fun any() = Mockito.any(T::class.java) ?: createInstance() diff --git a/mockito-kotlin/src/test/kotlin/ArgumentCaptorTest.kt b/mockito-kotlin/src/test/kotlin/ArgumentCaptorTest.kt new file mode 100644 index 00000000..8f4afc25 --- /dev/null +++ b/mockito-kotlin/src/test/kotlin/ArgumentCaptorTest.kt @@ -0,0 +1,20 @@ +import com.nhaarman.mockito_kotlin.argumentCaptor +import com.nhaarman.mockito_kotlin.mock +import com.nhaarman.mockito_kotlin.verify +import com.nhaarman.expect.expect +import com.nhaarman.mockito_kotlin.capture +import org.junit.Test +import java.util.* + +class ArgumentCaptorTest { + @Test + fun captor() { + val date: Date = mock() + val time = argumentCaptor() + + date.time = 5L + + verify(date).time = capture(time) + expect(time.value).toBe(5L) + } +} \ No newline at end of file From 9238c4cd2de64ad385c4a26be29047c05e1e0bc4 Mon Sep 17 00:00:00 2001 From: "Anton Keks, Dmitri Ess" Date: Tue, 8 Mar 2016 16:51:00 +0200 Subject: [PATCH 7/8] add simpler capture() method with lambda --- .../kotlin/com/nhaarman/mockito_kotlin/Mockito.kt | 4 ++++ mockito-kotlin/src/test/kotlin/ArgumentCaptorTest.kt | 12 +++++++++++- 2 files changed, 15 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 4d8a7d4a..549ad2f2 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 @@ -58,6 +58,10 @@ fun Stubber.whenever(mock: T) = `when`(mock) inline fun argumentCaptor() = ArgumentCaptor.forClass(T::class.java) inline fun capture(captor: ArgumentCaptor): T = captor.capture() ?: createInstance() +inline fun capture(noinline consumer: (T) -> Unit): T { + var times = 0 + return argThat { if (++times == 1) consumer.invoke(this); true } +} inline fun eq(value: T) = Mockito.eq(value) ?: createInstance() inline fun anyArray(): Array = Mockito.any(Array::class.java) ?: arrayOf() diff --git a/mockito-kotlin/src/test/kotlin/ArgumentCaptorTest.kt b/mockito-kotlin/src/test/kotlin/ArgumentCaptorTest.kt index 8f4afc25..9773e76d 100644 --- a/mockito-kotlin/src/test/kotlin/ArgumentCaptorTest.kt +++ b/mockito-kotlin/src/test/kotlin/ArgumentCaptorTest.kt @@ -8,7 +8,7 @@ import java.util.* class ArgumentCaptorTest { @Test - fun captor() { + fun explicitCaptor() { val date: Date = mock() val time = argumentCaptor() @@ -17,4 +17,14 @@ class ArgumentCaptorTest { verify(date).time = capture(time) expect(time.value).toBe(5L) } + + @Test + fun implicitCaptor() { + val date: Date = mock() + date.time = 5L + + verify(date).time = capture { + expect(it).toBe(5L) + } + } } \ No newline at end of file From 5105493f244ec811163dc0f1b94177e19adb9619 Mon Sep 17 00:00:00 2001 From: Niek Haarman Date: Thu, 10 Mar 2016 13:11:57 +0100 Subject: [PATCH 8/8] Include more static Mockito methods --- gradle/wrapper/gradle-wrapper.properties | 2 +- .../mockito_kotlin/ArgumentCaptor.kt} | 31 +-- .../nhaarman/mockito_kotlin/CreateInstance.kt | 2 +- .../com/nhaarman/mockito_kotlin/Mockito.kt | 85 ++++-- .../com/nhaarman/mockito_kotlin/Stubber.kt | 30 ++ .../src/test/kotlin/ArgumentCaptorTest.kt | 1 + .../src/test/kotlin/{Fake.kt => Classes.kt} | 29 +- .../src/test/kotlin/CreateInstanceTest.kt | 4 +- mockito-kotlin/src/test/kotlin/EqTest.kt | 2 +- mockito-kotlin/src/test/kotlin/MockitoTest.kt | 257 ++++++++++++++++++ 10 files changed, 382 insertions(+), 61 deletions(-) rename mockito-kotlin/src/{test/kotlin/MatcherTest.kt => main/kotlin/com/nhaarman/mockito_kotlin/ArgumentCaptor.kt} (67%) create mode 100644 mockito-kotlin/src/main/kotlin/com/nhaarman/mockito_kotlin/Stubber.kt rename mockito-kotlin/src/test/kotlin/{Fake.kt => Classes.kt} (65%) create mode 100644 mockito-kotlin/src/test/kotlin/MockitoTest.kt diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 909374a8..8ccb210f 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.10-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.11-all.zip diff --git a/mockito-kotlin/src/test/kotlin/MatcherTest.kt b/mockito-kotlin/src/main/kotlin/com/nhaarman/mockito_kotlin/ArgumentCaptor.kt similarity index 67% rename from mockito-kotlin/src/test/kotlin/MatcherTest.kt rename to mockito-kotlin/src/main/kotlin/com/nhaarman/mockito_kotlin/ArgumentCaptor.kt index 770c67f4..cffb582a 100644 --- a/mockito-kotlin/src/test/kotlin/MatcherTest.kt +++ b/mockito-kotlin/src/main/kotlin/com/nhaarman/mockito_kotlin/ArgumentCaptor.kt @@ -23,32 +23,9 @@ * THE SOFTWARE. */ -import com.nhaarman.mockito_kotlin.argThat -import com.nhaarman.mockito_kotlin.mock -import com.nhaarman.mockito_kotlin.verify -import org.junit.Test +package com.nhaarman.mockito_kotlin -class MatcherTest { +import org.mockito.ArgumentCaptor - @Test - fun argThat() { - /* Given */ - val testClass: TestClass = mock() - - /* When */ - testClass.go(listOf("test")) - - /* Then */ - verify(testClass).go( - argThat { - size == 1 - get(0) == "test" - } - ) - } - - interface TestClass { - - fun go(v: List) - } -} +inline fun argumentCaptor() = ArgumentCaptor.forClass(T::class.java) +inline fun capture(captor: ArgumentCaptor): T = captor.capture() ?: createInstance() 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 3815da89..4d9558c9 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 @@ -100,7 +100,7 @@ private fun KClass.toArrayInstance(): T { "LongArray" -> longArrayOf() "DoubleArray" -> doubleArrayOf() "FloatArray" -> floatArrayOf() - else -> throw UnsupportedOperationException("Cannot create a generic array for $simpleName. Use createArrayInstance() instead.") + else -> throw UnsupportedOperationException("Cannot create a generic array for $simpleName. Use createArrayInstance() or anyArray() instead.") } as T } 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 4d8a7d4a..a12b8f3f 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 @@ -25,47 +25,78 @@ package com.nhaarman.mockito_kotlin -import org.mockito.ArgumentCaptor +import org.mockito.MockSettings import org.mockito.Mockito +import org.mockito.invocation.InvocationOnMock import org.mockito.stubbing.Answer -import org.mockito.stubbing.Stubber import org.mockito.verification.VerificationMode import kotlin.reflect.KClass -inline fun mock() = Mockito.mock(T::class.java) -inline fun mock(defaultAnswer: Answer) = Mockito.mock(T::class.java, defaultAnswer) -fun spy(value: T) = Mockito.spy(value) +fun after(millis: Long) = Mockito.after(millis) -fun whenever(methodCall: T) = Mockito.`when`(methodCall) -fun verify(mock: T) = Mockito.verify(mock) -fun verify(mock: T, mode: VerificationMode) = Mockito.verify(mock, mode) -fun verifyNoMoreInteractions(mock: T) = Mockito.verifyNoMoreInteractions(mock) -fun reset(mock: T) = Mockito.reset(mock) +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 argThat(noinline predicate: T.() -> Boolean) = Mockito.argThat { it -> (it as T).predicate() } ?: createInstance(T::class) -fun inOrder(vararg value: Any) = Mockito.inOrder(*value) -fun never() = Mockito.never() -fun times(numInvocations: Int) = Mockito.times(numInvocations) fun atLeast(numInvocations: Int) = Mockito.atLeast(numInvocations) fun atLeastOnce() = Mockito.atLeastOnce() +fun atMost(maxNumberOfInvocations: Int) = Mockito.atMost(maxNumberOfInvocations) +fun calls(wantedNumberOfInvocations: Int) = Mockito.calls(wantedNumberOfInvocations) -fun doReturn(value: Any) = Mockito.doReturn(value) -fun doThrow(throwable: Throwable) = Mockito.doThrow(throwable) -fun doAnswer(answer: Answer) = Mockito.doAnswer(answer) -fun doCallRealMethod() = Mockito.doCallRealMethod() -fun doNothing() = Mockito.doNothing() +fun clearInvocations(vararg mocks: T) = Mockito.clearInvocations(*mocks) +fun description(description: String) = Mockito.description(description) -fun Stubber.whenever(mock: T) = `when`(mock) +fun doAnswer(answer: (InvocationOnMock) -> T?) = Mockito.doAnswer { answer(it) } -inline fun argumentCaptor() = ArgumentCaptor.forClass(T::class.java) -inline fun capture(captor: ArgumentCaptor): T = captor.capture() ?: createInstance() +fun doCallRealMethod() = Mockito.doCallRealMethod() +fun doNothing() = Mockito.doNothing() +fun doReturn(value: Any) = Mockito.doReturn(value) +fun doReturn(toBeReturned: Any, vararg toBeReturnedNext: Any) = Mockito.doReturn(toBeReturned, *toBeReturnedNext) +fun doThrow(toBeThrown: KClass) = Mockito.doThrow(toBeThrown.java) +fun doThrow(vararg toBeThrown: Throwable) = Mockito.doThrow(*toBeThrown) inline fun eq(value: T) = Mockito.eq(value) ?: createInstance() -inline fun anyArray(): Array = Mockito.any(Array::class.java) ?: arrayOf() -inline fun any() = Mockito.any(T::class.java) ?: createInstance() +fun ignoreStubs(vararg mocks: Any) = Mockito.ignoreStubs(*mocks) +fun inOrder(vararg mocks: Any) = Mockito.inOrder(*mocks) + +inline fun isA() = Mockito.isA(T::class.java) +inline fun isNotNull() = Mockito.isNotNull(T::class.java) inline fun isNull(): T? = Mockito.isNull(T::class.java) -inline fun argThat(noinline predicate: T.() -> Boolean) = argThat(T::class, predicate) +inline fun mock() = Mockito.mock(T::class.java) +inline fun mock(defaultAnswer: Answer) = Mockito.mock(T::class.java, defaultAnswer) +inline fun mock(s: MockSettings) = Mockito.mock(T::class.java, s) +inline fun mock(s: String) = Mockito.mock(T::class.java, s) + +fun mockingDetails(toInspect: Any) = Mockito.mockingDetails(toInspect) +fun never() = Mockito.never() +inline fun notNull() = Mockito.notNull(T::class.java) +fun only() = Mockito.only() +fun refEq(value: T, vararg excludeFields: String) = Mockito.refEq(value, *excludeFields) + +fun reset() = Mockito.reset() +fun reset(vararg mocks: T) = Mockito.reset(*mocks) -@Suppress("UNCHECKED_CAST") -fun argThat(kClass: KClass, predicate: T.() -> Boolean) - = Mockito.argThat { it -> (it as T).predicate() } ?: createInstance(kClass) +fun same(value: T) = Mockito.same(value) + +inline fun spy() = Mockito.spy(T::class.java) +fun spy(value: T) = Mockito.spy(value) + +fun stub(methodCall: T) = Mockito.stub(methodCall) +fun timeout(millis: Long) = Mockito.timeout(millis) +fun times(numInvocations: Int) = Mockito.times(numInvocations) +fun validateMockitoUsage() = Mockito.validateMockitoUsage() + +fun verify(mock: T) = Mockito.verify(mock) +fun verify(mock: T, mode: VerificationMode) = Mockito.verify(mock, mode) +fun verifyNoMoreInteractions(vararg mocks: T) = Mockito.verifyNoMoreInteractions(*mocks) +fun verifyZeroInteractions(vararg mocks: Any) = Mockito.verifyZeroInteractions(*mocks) + +fun whenever(methodCall: T) = Mockito.`when`(methodCall) +fun withSettings() = Mockito.withSettings() \ No newline at end of file diff --git a/mockito-kotlin/src/main/kotlin/com/nhaarman/mockito_kotlin/Stubber.kt b/mockito-kotlin/src/main/kotlin/com/nhaarman/mockito_kotlin/Stubber.kt new file mode 100644 index 00000000..cfb0bd52 --- /dev/null +++ b/mockito-kotlin/src/main/kotlin/com/nhaarman/mockito_kotlin/Stubber.kt @@ -0,0 +1,30 @@ +/* + * The MIT License + * + * Copyright (c) 2016 Niek Haarman + * Copyright (c) 2007 Mockito contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.nhaarman.mockito_kotlin + +import org.mockito.stubbing.Stubber + +fun Stubber.whenever(mock: T) = `when`(mock) diff --git a/mockito-kotlin/src/test/kotlin/ArgumentCaptorTest.kt b/mockito-kotlin/src/test/kotlin/ArgumentCaptorTest.kt index 8f4afc25..8b5ec920 100644 --- a/mockito-kotlin/src/test/kotlin/ArgumentCaptorTest.kt +++ b/mockito-kotlin/src/test/kotlin/ArgumentCaptorTest.kt @@ -7,6 +7,7 @@ import org.junit.Test import java.util.* class ArgumentCaptorTest { + @Test fun captor() { val date: Date = mock() diff --git a/mockito-kotlin/src/test/kotlin/Fake.kt b/mockito-kotlin/src/test/kotlin/Classes.kt similarity index 65% rename from mockito-kotlin/src/test/kotlin/Fake.kt rename to mockito-kotlin/src/test/kotlin/Classes.kt index 7aa9743c..f0ff2dfd 100644 --- a/mockito-kotlin/src/test/kotlin/Fake.kt +++ b/mockito-kotlin/src/test/kotlin/Classes.kt @@ -23,7 +23,32 @@ * THE SOFTWARE. */ -open class Fake { - open fun go(arg: Any?) { +open class Open { + open fun go(vararg arg: Any?) { } + + open fun modifiesContents(a: IntArray) { + for (i in 0..a.size - 1) { + a[i] = a[i] + 1 + } + } + + open fun stringResult() = "Default" +} + +class Closed + +interface Methods { + + fun intArray(i: IntArray) + fun closed(c: Closed) + fun closedArray(a: Array) + fun closedCollection(c: Collection) + fun closedList(c: List) + fun closedStringMap(m: Map) + fun closedSet(s: Set) + fun string(s: String) + fun closedVararg(vararg c: Closed) + + fun stringResult(): String } \ No newline at end of file diff --git a/mockito-kotlin/src/test/kotlin/CreateInstanceTest.kt b/mockito-kotlin/src/test/kotlin/CreateInstanceTest.kt index ca494172..1bfcd917 100644 --- a/mockito-kotlin/src/test/kotlin/CreateInstanceTest.kt +++ b/mockito-kotlin/src/test/kotlin/CreateInstanceTest.kt @@ -158,7 +158,7 @@ class CreateInstanceTest { @Test(expected = UnsupportedOperationException::class) fun classArray_usingAny() { /* When */ - createInstance>() + createInstance>() } @Test @@ -371,7 +371,7 @@ class CreateInstanceTest { private class PrivateClass private constructor(val data: String) class ClosedClass - class ClosedParameterizedClass(val fake: Fake) + class ClosedParameterizedClass(val open: Open) class ClosedClosedParameterizedClass(val closed: ClosedParameterizedClass) class SingleParameterClass(val first: Byte) diff --git a/mockito-kotlin/src/test/kotlin/EqTest.kt b/mockito-kotlin/src/test/kotlin/EqTest.kt index dd107664..3e4294db 100644 --- a/mockito-kotlin/src/test/kotlin/EqTest.kt +++ b/mockito-kotlin/src/test/kotlin/EqTest.kt @@ -37,7 +37,7 @@ class EqTest { private val openClassInstance: MyClass = MyClass() private val closedClassInstance: ClosedClass = ClosedClass() - private lateinit var doAnswer: Fake + private lateinit var doAnswer: Open @Before fun setup() { diff --git a/mockito-kotlin/src/test/kotlin/MockitoTest.kt b/mockito-kotlin/src/test/kotlin/MockitoTest.kt new file mode 100644 index 00000000..394594b2 --- /dev/null +++ b/mockito-kotlin/src/test/kotlin/MockitoTest.kt @@ -0,0 +1,257 @@ +import com.nhaarman.expect.expect +import com.nhaarman.expect.expectErrorWithMessage +import com.nhaarman.mockito_kotlin.* +import org.junit.Test +import org.mockito.exceptions.base.MockitoAssertionError + +/* + * The MIT License + * + * Copyright (c) 2016 Niek Haarman + * Copyright (c) 2007 Mockito contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +class MockitoTest { + + @Test + fun anyString() { + mock().apply { + string("") + verify(this).string(any()) + } + } + + @Test + fun anyClosedClass() { + mock().apply { + closed(Closed()) + verify(this).closed(any()) + } + } + + @Test + fun anyIntArray() { + mock().apply { + intArray(intArrayOf()) + verify(this).intArray(any()) + } + } + + @Test + fun anyClassArray() { + mock().apply { + closedArray(arrayOf(Closed())) + verify(this).closedArray(anyArray()) + } + } + + @Test + fun anyCollectionOfClosed() { + mock().apply { + closedCollection(listOf()) + verify(this).closedCollection(any()) + verify(this).closedCollection(anyCollection()) + } + } + + @Test + fun anyListOfClosed() { + mock().apply { + closedList(listOf()) + verify(this).closedList(any()) + verify(this).closedList(anyList()) + } + } + + @Test + fun anyClosedStringMap() { + mock().apply { + closedStringMap(mapOf()) + verify(this).closedStringMap(any()) + verify(this).closedStringMap(anyMap()) + } + } + + @Test + fun anyClosedSet() { + mock().apply { + closedSet(setOf()) + verify(this).closedSet(any()) + verify(this).closedSet(anySet()) + } + } + + @Test + fun anyStringVararg() { + mock().apply { + closedVararg(Closed(), Closed()) + verify(this).closedVararg(anyVararg()) + } + } + + @Test + fun listArgThat() { + mock().apply { + closedList(listOf(Closed(), Closed())) + verify(this).closedList(argThat { + size == 2 + }) + } + } + + @Test + fun atLeastXInvocations() { + mock().apply { + string("") + string("") + + verify(this, atLeast(2)).string(any()) + } + } + + @Test + fun testAtLeastOnce() { + mock().apply { + string("") + string("") + + verify(this, atLeastOnce()).string(any()) + } + } + + @Test + fun atMostXInvocations() { + mock().apply { + string("") + string("") + + verify(this, atMost(2)).string(any()) + } + } + + @Test + fun testCalls() { + mock().apply { + string("") + string("") + + inOrder(this).verify(this, calls(2)).string(any()) + } + } + + @Test + fun testClearInvocations() { + val mock = mock().apply { + string("") + } + + clearInvocations(mock) + + verify(mock, never()).string(any()) + } + + @Test + fun testDescription() { + try { + mock().apply { + verify(this, description("Test")).string(any()) + } + throw AssertionError("Verify should throw Exception.") + } catch (e: MockitoAssertionError) { + expect(e.message).toContain("Test") + } + } + + @Test + fun testDoAnswer() { + val mock = mock() + + doAnswer { "Test" } + .whenever(mock) + .stringResult() + + expect(mock.stringResult()).toBe("Test") + } + + @Test + fun testDoCallRealMethod() { + val mock = mock() + + doReturn("Test").whenever(mock).stringResult() + doCallRealMethod().whenever(mock).stringResult() + + expect(mock.stringResult()).toBe("Default") + } + + @Test + fun testDoNothing() { + val spy = spy(Open()) + val array = intArrayOf(3) + + doNothing().whenever(spy).modifiesContents(array) + spy.modifiesContents(array) + + expect(array[0]).toBe(3) + } + + @Test + fun testDoReturnValue() { + val mock = mock() + + doReturn("test").whenever(mock).stringResult() + + expect(mock.stringResult()).toBe("test") + } + + @Test + fun testDoReturnValues() { + val mock = mock() + + doReturn("test", "test2").whenever(mock).stringResult() + + expect(mock.stringResult()).toBe("test") + expect(mock.stringResult()).toBe("test2") + } + + @Test + fun testDoThrowClass() { + val mock = mock() + + doThrow(IllegalStateException::class).whenever(mock).go() + + try { + mock.go() + throw AssertionError("Call should have thrown.") + } catch(e: IllegalStateException) { + } + } + + @Test + fun testDoThrow() { + val mock = mock() + + doThrow(IllegalStateException("test")).whenever(mock).go() + + expectErrorWithMessage("test").on { + mock.go() + } + } +}