├── version.properties ├── gradle.properties ├── tests ├── settings.gradle ├── gradle.properties ├── src │ └── test │ │ └── kotlin │ │ └── test │ │ ├── TestBase.kt │ │ ├── MockMaker.kt │ │ ├── createinstance │ │ └── NullCasterTest.kt │ │ ├── LenientStubberTest.kt │ │ ├── VerifyTest.kt │ │ ├── VerificationTest.kt │ │ ├── AdditionalMatchersTest.kt │ │ ├── StubberTest.kt │ │ ├── EqTest.kt │ │ ├── Classes.kt │ │ ├── BDDMockitoTest.kt │ │ ├── inline │ │ └── UsingMockMakerInlineTest.kt │ │ ├── SpyTest.kt │ │ ├── ArgumentCaptorTest.kt │ │ ├── MatchersTest.kt │ │ ├── OngoingStubbingTest.kt │ │ └── MockingTest.kt ├── README.md └── build.gradle ├── ops ├── org.mockito.plugins.MockMaker └── mockMakerInline.sh ├── settings.gradle ├── gradle ├── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties └── publishing.gradle ├── .github ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── ci.yml ├── .idea ├── codeStyles │ ├── codeStyleConfig.xml │ └── Project.xml ├── copyright │ ├── profiles_settings.xml │ └── MIT.xml └── inspectionProfiles │ └── Project_Default.xml ├── .gitignore ├── RELEASING.md ├── LICENSE ├── mockito-kotlin ├── src │ ├── main │ │ └── kotlin │ │ │ └── org │ │ │ └── mockito │ │ │ └── kotlin │ │ │ ├── MockitoKotlinException.kt │ │ │ ├── Mockito.kt │ │ │ ├── LenientStubber.kt │ │ │ ├── VerifyScope.kt │ │ │ ├── internal │ │ │ ├── KInOrderDecorator.kt │ │ │ ├── CreateInstance.kt │ │ │ └── SuspendableAnswer.kt │ │ │ ├── KInOrder.kt │ │ │ ├── Spying.kt │ │ │ ├── Stubber.kt │ │ │ ├── KStubbing.kt │ │ │ ├── OngoingStubbing.kt │ │ │ ├── BDDMockito.kt │ │ │ ├── Matchers.kt │ │ │ ├── AdditionalMatchers.kt │ │ │ ├── ArgumentCaptor.kt │ │ │ ├── Verification.kt │ │ │ └── Mocking.kt │ └── test │ │ └── kotlin │ │ ├── org │ │ └── mockito │ │ │ └── kotlin │ │ │ └── BDDMockitoKtTest.kt │ │ └── test │ │ └── CoroutinesTest.kt └── build.gradle ├── README.md ├── gradlew.bat └── gradlew /version.properties: -------------------------------------------------------------------------------- 1 | tagPrefix= 2 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | isRelease=false 2 | -------------------------------------------------------------------------------- /tests/settings.gradle: -------------------------------------------------------------------------------- 1 | includeBuild '..' 2 | -------------------------------------------------------------------------------- /ops/org.mockito.plugins.MockMaker: -------------------------------------------------------------------------------- 1 | mock-maker-inline -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include 'mockito-kotlin' 2 | includeBuild 'tests' 3 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mustafa-Hassan2001/mockito-kotlin/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thank you for submitting a pull request! But first: 2 | 3 | - [ ] Can you back your code up with tests? 4 | -------------------------------------------------------------------------------- /tests/gradle.properties: -------------------------------------------------------------------------------- 1 | # Default version for the :tests module for Kotlin StdLib / KGP. 2 | # See https://github.com/mockito/mockito-kotlin#testing for more. 3 | testKotlinVersion=1.9.20 4 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | build/ 3 | out/ 4 | repo 5 | 6 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 7 | !gradle-wrapper.jar 8 | 9 | # intelliJ 10 | .idea/ 11 | *.iml 12 | 13 | *.orig 14 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /tests/src/test/kotlin/test/TestBase.kt: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import org.junit.After 4 | 5 | abstract class TestBase { 6 | 7 | @After 8 | open fun tearDown() { 9 | mockMakerInlineEnabled = null 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /ops/mockMakerInline.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ev 4 | 5 | if [ ${MOCK_MAKER} = "mock-maker-inline" ]; then 6 | mkdir -p tests/src/test/resources/mockito-extensions 7 | cp ops/org.mockito.plugins.MockMaker tests/src/test/resources/mockito-extensions/ 8 | fi 9 | 10 | exit 0; 11 | 12 | -------------------------------------------------------------------------------- /tests/README.md: -------------------------------------------------------------------------------- 1 | Mockito-Kotlin tests 2 | ==================== 3 | 4 | Tests should be placed in this module. 5 | CI is set up to execute tests for all major versions of Kotlin, 6 | whilst keeping the library version on the latest version. 7 | This ensures the library is backwards compatible for all Kotlin versions. 8 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /tests/src/test/kotlin/test/MockMaker.kt: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import org.mockito.internal.configuration.plugins.Plugins 4 | import org.mockito.internal.creation.bytebuddy.InlineByteBuddyMockMaker 5 | 6 | internal var mockMakerInlineEnabled: Boolean? = null 7 | 8 | internal fun mockMakerInlineEnabled(): Boolean { 9 | return mockMakerInlineEnabled ?: (Plugins.getMockMaker() is InlineByteBuddyMockMaker) 10 | } 11 | -------------------------------------------------------------------------------- /RELEASING.md: -------------------------------------------------------------------------------- 1 | # Releasing 2 | 3 | 1. Every change on the main development branch is released as -SNAPSHOT version 4 | to Sonatype snapshot repo at https://s01.oss.sonatype.org/content/repositories/snapshots/org/mockito/kotlin/mockito-kotlin. 5 | 2. In order to release a non-snapshot version to Maven Central push an annotated tag, for example: 6 | ``` 7 | git tag -a -m "Release 3.4.5" 3.4.5 8 | git push origin 3.4.5 9 | ``` 10 | 3. At the moment, you **may not create releases from GitHub Web UI**. 11 | Doing so will make the CI build fail because the CI creates the changelog and posts to GitHub releases. 12 | In the future supporting this would be nice but currently please make releases by pushing from CLI. 13 | -------------------------------------------------------------------------------- /tests/src/test/kotlin/test/createinstance/NullCasterTest.kt: -------------------------------------------------------------------------------- 1 | package test.createinstance 2 | 3 | import com.nhaarman.expect.expect 4 | import org.mockito.kotlin.internal.createInstance 5 | import org.junit.Test 6 | import test.TestBase 7 | 8 | class NullCasterTest : TestBase() { 9 | 10 | @Test 11 | fun createInstance() { 12 | /* When */ 13 | val result = createInstance(String::class) 14 | 15 | /* Then */ 16 | expect(result).toBeNull() 17 | } 18 | 19 | @Test 20 | fun kotlinAcceptsNullValue() { 21 | /* Given */ 22 | val s: String = createInstance(String::class) 23 | 24 | /* When */ 25 | acceptNonNullableString(s) 26 | } 27 | 28 | private fun acceptNonNullableString(@Suppress("UNUSED_PARAMETER") s: String) { 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/build.gradle: -------------------------------------------------------------------------------- 1 | import org.jetbrains.kotlin.gradle.dsl.JvmTarget 2 | import org.jetbrains.kotlin.gradle.tasks.KotlinCompile 3 | 4 | plugins { 5 | id "org.gradle.java" 6 | id "org.jetbrains.kotlin.jvm" version "${testKotlinVersion}" 7 | } 8 | 9 | logger.lifecycle "${project} uses Kotlin ${testKotlinVersion}" 10 | 11 | repositories { 12 | mavenCentral() 13 | } 14 | 15 | dependencies { 16 | implementation "org.mockito.kotlin:mockito-kotlin" 17 | 18 | implementation "org.jetbrains.kotlin:kotlin-stdlib" 19 | 20 | testImplementation 'junit:junit:4.13.2' 21 | testImplementation "com.nhaarman:expect.kt:1.0.1" 22 | } 23 | 24 | tasks.withType(KotlinCompile).configureEach { 25 | compilerOptions { 26 | jvmTarget.set(JvmTarget.JVM_11) 27 | targetCompatibility = "11" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2016 Niek Haarman 4 | Copyright (c) 2007 Mockito contributors 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. -------------------------------------------------------------------------------- /.idea/copyright/MIT.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /mockito-kotlin/src/main/kotlin/org/mockito/kotlin/MockitoKotlinException.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018 Niek Haarman 5 | * Copyright (c) 2007 Mockito contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | package org.mockito.kotlin 27 | 28 | class MockitoKotlinException(message: String?, cause: Throwable?) : RuntimeException(message, cause) 29 | -------------------------------------------------------------------------------- /mockito-kotlin/build.gradle: -------------------------------------------------------------------------------- 1 | import org.jetbrains.kotlin.gradle.dsl.JvmTarget 2 | import org.jetbrains.kotlin.gradle.tasks.KotlinCompile 3 | 4 | plugins { 5 | id "org.jetbrains.kotlin.jvm" 6 | id "org.jetbrains.dokka" 7 | } 8 | apply from: '../gradle/publishing.gradle' 9 | 10 | group = 'org.mockito.kotlin' 11 | 12 | repositories { 13 | mavenCentral() 14 | } 15 | 16 | dependencies { 17 | compileOnly "org.jetbrains.kotlin:kotlin-stdlib" 18 | compileOnly 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.0.0' 19 | 20 | api "org.mockito:mockito-core:5.7.0" 21 | 22 | testImplementation 'junit:junit:4.13.2' 23 | testImplementation 'com.nhaarman:expect.kt:1.0.1' 24 | 25 | testImplementation "org.jetbrains.kotlin:kotlin-stdlib" 26 | testImplementation "org.jetbrains.kotlin:kotlin-test" 27 | testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.0' 28 | 29 | testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.0" 30 | } 31 | 32 | dokkaHtml.configure { 33 | outputDirectory.set(file("$buildDir/javadoc")) 34 | 35 | dokkaSourceSets { 36 | named("main") { 37 | localDirectory.set(file("src/main/kotlin")) 38 | remoteUrl.set(new URL("https://github.com/nhaarman/mockito-kotlin/tree/master/mockito-kotlin/src/main/kotlin")) 39 | remoteLineSuffix.set("#L") 40 | } 41 | } 42 | } 43 | 44 | tasks.withType(KotlinCompile).configureEach { 45 | compilerOptions { 46 | jvmTarget.set(JvmTarget.JVM_11) 47 | targetCompatibility = "11" 48 | } 49 | } 50 | 51 | javadoc.dependsOn dokkaHtml 52 | -------------------------------------------------------------------------------- /mockito-kotlin/src/main/kotlin/org/mockito/kotlin/Mockito.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018 Niek Haarman 5 | * Copyright (c) 2007 Mockito contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | package org.mockito.kotlin 27 | 28 | import org.mockito.MockingDetails 29 | import org.mockito.Mockito 30 | 31 | fun validateMockitoUsage() { 32 | Mockito.validateMockitoUsage() 33 | } 34 | 35 | fun reset(vararg mocks: T) { 36 | Mockito.reset(*mocks) 37 | } 38 | 39 | fun mockingDetails(toInspect: Any): MockingDetails { 40 | return Mockito.mockingDetails(toInspect)!! 41 | } 42 | -------------------------------------------------------------------------------- /mockito-kotlin/src/main/kotlin/org/mockito/kotlin/LenientStubber.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018 Niek Haarman 5 | * Copyright (c) 2007 Mockito contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | package org.mockito.kotlin 27 | 28 | import org.mockito.stubbing.LenientStubber 29 | import org.mockito.stubbing.OngoingStubbing 30 | 31 | inline fun LenientStubber.whenever(methodCall: T): OngoingStubbing { 32 | return `when`(methodCall) 33 | } 34 | 35 | inline fun LenientStubber.whenever(methodCall: () -> T): OngoingStubbing { 36 | return whenever(methodCall()) 37 | } 38 | 39 | -------------------------------------------------------------------------------- /tests/src/test/kotlin/test/LenientStubberTest.kt: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import org.junit.Assert 4 | import org.junit.Rule 5 | import org.junit.Test 6 | import org.mockito.Mockito.lenient 7 | import org.mockito.junit.MockitoJUnit 8 | import org.mockito.junit.MockitoRule 9 | import org.mockito.kotlin.any 10 | import org.mockito.kotlin.doReturn 11 | import org.mockito.kotlin.mock 12 | import org.mockito.kotlin.whenever 13 | import org.mockito.quality.Strictness 14 | 15 | open class LenientStubberTest { 16 | @get:Rule 17 | val rule: MockitoRule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS) 18 | 19 | @Test 20 | fun unused_and_lenient_stubbings() { 21 | val mock = mock>() 22 | lenient().whenever(mock.add("one")).doReturn(true) 23 | whenever(mock[any()]).doReturn("hello") 24 | 25 | Assert.assertEquals("List should contain hello", "hello", mock[1]) 26 | } 27 | 28 | @Test 29 | fun unused_and_lenient_stubbings_with_unit() { 30 | val mock = mock>() 31 | lenient().whenever { mock.add("one") }.doReturn(true) 32 | whenever(mock[any()]).doReturn("hello") 33 | 34 | Assert.assertEquals("List should contain hello", "hello", mock[1]) 35 | } 36 | 37 | @Test 38 | fun unused_and_lenient_stubbings_with_nullable() { 39 | val mock = mock() 40 | lenient().whenever(mock.returnsNullableString()).doReturn(null) 41 | whenever(mock.returnsNonNullableString()).doReturn("hello") 42 | 43 | Assert.assertEquals("Should return hello", "hello", mock.returnsNonNullableString()) 44 | } 45 | 46 | private class NullableToString { 47 | fun returnsNullableString(): String? = "" 48 | fun returnsNonNullableString(): String = "" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /mockito-kotlin/src/main/kotlin/org/mockito/kotlin/VerifyScope.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018 Niek Haarman 5 | * Copyright (c) 2007 Mockito contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | package org.mockito.kotlin 27 | 28 | /** 29 | * Verify multiple calls on mock 30 | * Supports an easier to read style of 31 | * 32 | * ``` 33 | * verify(mock) { 34 | * 2 * { call() } 35 | * } 36 | * ``` 37 | */ 38 | inline fun verify(mock: T, block: VerifyScope.() -> Unit) { 39 | VerifyScope(mock).block() 40 | } 41 | 42 | class VerifyScope(val mock: T) { 43 | 44 | operator inline fun Int.times(call: T.() -> Unit) { 45 | verify(mock, org.mockito.kotlin.times(this)).call() 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /mockito-kotlin/src/main/kotlin/org/mockito/kotlin/internal/KInOrderDecorator.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018 Niek Haarman 5 | * Copyright (c) 2007 Mockito contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | package org.mockito.kotlin.internal 27 | 28 | import kotlinx.coroutines.runBlocking 29 | import org.mockito.InOrder 30 | import org.mockito.kotlin.KInOrder 31 | import org.mockito.verification.VerificationMode 32 | 33 | class KInOrderDecorator(private val inOrder: InOrder) : KInOrder, InOrder by inOrder { 34 | override fun verifyBlocking(mock: T, f: suspend T.() -> Unit) { 35 | val m = verify(mock) 36 | runBlocking { m.f() } 37 | } 38 | 39 | override fun verifyBlocking(mock: T, mode: VerificationMode, f: suspend T.() -> Unit) { 40 | val m = verify(mock, mode) 41 | runBlocking { m.f() } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /mockito-kotlin/src/main/kotlin/org/mockito/kotlin/KInOrder.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018 Niek Haarman 5 | * Copyright (c) 2007 Mockito contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | package org.mockito.kotlin 27 | 28 | import org.mockito.InOrder 29 | import org.mockito.verification.VerificationMode 30 | 31 | interface KInOrder : InOrder { 32 | /** 33 | * Verifies certain suspending behavior happened once in order. 34 | * 35 | * Warning: Only one method call can be verified in the function. 36 | * Subsequent method calls are ignored! 37 | */ 38 | fun verifyBlocking(mock: T, f: suspend T.() -> Unit) 39 | 40 | /** 41 | * Verifies certain suspending behavior happened at least once / exact number of times / never in order. 42 | * 43 | * Warning: Only one method call can be verified in the function. 44 | * Subsequent method calls are ignored! 45 | */ 46 | fun verifyBlocking(mock: T, mode: VerificationMode, f: suspend T.() -> Unit) 47 | } 48 | -------------------------------------------------------------------------------- /mockito-kotlin/src/main/kotlin/org/mockito/kotlin/internal/CreateInstance.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018 Niek Haarman 5 | * Copyright (c) 2007 Mockito contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | package org.mockito.kotlin.internal 27 | 28 | import kotlin.reflect.KClass 29 | 30 | inline fun createInstance(): T { 31 | return when (T::class) { 32 | Boolean::class -> false as T 33 | Byte::class -> 0.toByte() as T 34 | Char::class -> 0.toChar() as T 35 | Short::class -> 0.toShort() as T 36 | Int::class -> 0 as T 37 | Long::class -> 0L as T 38 | Float::class -> 0f as T 39 | Double::class -> 0.0 as T 40 | else -> createInstance(T::class) 41 | } 42 | } 43 | 44 | fun createInstance(@Suppress("UNUSED_PARAMETER") kClass: KClass): T { 45 | return castNull() 46 | } 47 | 48 | /** 49 | * Uses a quirk in the bytecode generated by Kotlin 50 | * to cast [null] to a non-null type. 51 | * 52 | * See https://youtrack.jetbrains.com/issue/KT-8135. 53 | */ 54 | @Suppress("UNCHECKED_CAST") 55 | private fun castNull(): T = null as T 56 | -------------------------------------------------------------------------------- /tests/src/test/kotlin/test/VerifyTest.kt: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import org.mockito.kotlin.any 4 | import org.mockito.kotlin.mock 5 | import org.mockito.kotlin.verify 6 | import org.junit.Test 7 | import org.mockito.exceptions.verification.TooFewActualInvocations 8 | import org.mockito.exceptions.verification.junit.ArgumentsAreDifferent 9 | 10 | class VerifyTest : TestBase() { 11 | 12 | @Test 13 | fun verify0Calls() { 14 | val iface = mock() 15 | 16 | verify(iface) { 17 | 0 * { call(any()) } 18 | } 19 | } 20 | 21 | @Test 22 | fun verifyNCalls() { 23 | val iface = mock() 24 | 25 | iface.call(42) 26 | iface.call(42) 27 | 28 | verify(iface) { 29 | 2 * { call(42) } 30 | } 31 | } 32 | 33 | @Test(expected = TooFewActualInvocations::class) 34 | fun verifyFailsWithWrongCount() { 35 | val iface = mock() 36 | 37 | iface.call(0) 38 | 39 | verify(iface) { 40 | 2 * { call(0) } 41 | } 42 | } 43 | 44 | @Test(expected = ArgumentsAreDifferent::class) 45 | fun verifyFailsWithWrongArg() { 46 | val iface = mock() 47 | 48 | iface.call(3) 49 | 50 | verify(iface) { 51 | 1 * { call(0) } 52 | } 53 | } 54 | 55 | @Test 56 | fun verifyDefaultArgs_firstParameter() { 57 | /* Given */ 58 | val m = mock() 59 | 60 | /* When */ 61 | m.defaultArgs(a = 2) 62 | 63 | /* Then */ 64 | verify(m).defaultArgs(2) 65 | } 66 | 67 | @Test 68 | fun verifyDefaultArgs_secondParameter() { 69 | /* Given */ 70 | val m = mock() 71 | 72 | /* When */ 73 | m.defaultArgs(b = 2) 74 | 75 | /* Then */ 76 | verify(m).defaultArgs(b = 2) 77 | } 78 | 79 | @Test 80 | fun verifyDefaultArgs_verifyDefaultValue() { 81 | /* Given */ 82 | val m = mock() 83 | 84 | /* When */ 85 | m.defaultArgs(b = 2) 86 | 87 | /* Then */ 88 | verify(m).defaultArgs(a = 3, b = 2) 89 | } 90 | 91 | interface TestInterface { 92 | fun call(arg: Int) 93 | 94 | fun defaultArgs(a: Int = 3, b: Int = 42) 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /mockito-kotlin/src/main/kotlin/org/mockito/kotlin/internal/SuspendableAnswer.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018 Niek Haarman 5 | * Copyright (c) 2007 Mockito contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | package org.mockito.kotlin.internal 27 | 28 | import org.mockito.internal.invocation.InterceptedInvocation 29 | import org.mockito.invocation.InvocationOnMock 30 | import org.mockito.stubbing.Answer 31 | import kotlin.coroutines.Continuation 32 | import kotlin.coroutines.intrinsics.startCoroutineUninterceptedOrReturn 33 | 34 | /** 35 | * This class properly wraps suspendable lambda into [Answer] 36 | */ 37 | @Suppress("UNCHECKED_CAST") 38 | internal class SuspendableAnswer( 39 | private val body: suspend (InvocationOnMock) -> T? 40 | ) : Answer { 41 | override fun answer(invocation: InvocationOnMock?): T { 42 | //all suspend functions/lambdas has Continuation as the last argument. 43 | //InvocationOnMock does not see last argument 44 | val rawInvocation = invocation as InterceptedInvocation 45 | val continuation = rawInvocation.rawArguments.last() as Continuation 46 | 47 | // https://youtrack.jetbrains.com/issue/KT-33766#focus=Comments-27-3707299.0-0 48 | return body.startCoroutineUninterceptedOrReturn(invocation, continuation) as T 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /gradle/publishing.gradle: -------------------------------------------------------------------------------- 1 | //Maven publication plugins & configuration 2 | apply plugin: 'maven-publish' 3 | 4 | task javadocJar(type: Jar, dependsOn: javadoc) { 5 | archiveClassifier = 'javadoc' 6 | from 'build/javadoc' 7 | } 8 | 9 | task sourceJar(type: Jar) { 10 | archiveClassifier = "sources" 11 | from sourceSets.main.allSource 12 | } 13 | 14 | publishing { 15 | publications { 16 | javaLibrary(MavenPublication) { 17 | artifactId 'mockito-kotlin' 18 | 19 | from components.java 20 | 21 | artifact sourceJar 22 | artifact javadocJar 23 | 24 | pom.withXml { 25 | def root = asNode() 26 | root.appendNode('name', 'Mockito-Kotlin') 27 | root.appendNode('description', 'Using Mockito with Kotlin.') 28 | root.appendNode('url', 'https://github.com/mockito/mockito-kotlin') 29 | 30 | def scm = root.appendNode('scm') 31 | scm.appendNode('url', 'scm:git@github.com:mockito/mockito-kotlin.git') 32 | 33 | def licenses = root.appendNode('licenses') 34 | def mitLicense = licenses.appendNode('license') 35 | mitLicense.appendNode('name', 'MIT') 36 | 37 | def developers = root.appendNode('developers') 38 | def nhaarman = developers.appendNode('developer') 39 | nhaarman.appendNode('id', 'nhaarman') 40 | nhaarman.appendNode('name', 'Niek Haarman') 41 | } 42 | } 43 | } 44 | 45 | //useful for testing - running "publish" will create artifacts/pom in a local dir 46 | repositories { maven { url = "$rootProject.buildDir/repo" } } 47 | } 48 | 49 | clean { 50 | delete "$rootProject.buildDir/repo" 51 | } 52 | 53 | // Avoid generation of the module metadata so that we don't have to publish an additional file 54 | // and keep the build logic simple. 55 | tasks.withType(GenerateModuleMetadata) { 56 | enabled = false 57 | } 58 | 59 | //fleshes out problems with Maven pom generation when building 60 | tasks.build.dependsOn('publishJavaLibraryPublicationToMavenLocal') 61 | 62 | apply plugin: 'signing' //https://docs.gradle.org/current/userguide/signing_plugin.html 63 | signing { 64 | if (System.getenv("PGP_KEY")) { 65 | useInMemoryPgpKeys(System.getenv("PGP_KEY"), System.getenv("PGP_PWD")) 66 | sign publishing.publications.javaLibrary 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /mockito-kotlin/src/main/kotlin/org/mockito/kotlin/Spying.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018 Niek Haarman 5 | * Copyright (c) 2007 Mockito contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | package org.mockito.kotlin 27 | 28 | import org.mockito.Mockito 29 | 30 | /** 31 | * Creates a spy of the real object. 32 | * The spy calls real methods unless they are stubbed. 33 | */ 34 | inline fun spy(): T { 35 | return Mockito.spy(T::class.java)!! 36 | } 37 | 38 | /** 39 | * Creates a spy of the real object, allowing for immediate stubbing. 40 | * The spy calls real methods unless they are stubbed. 41 | */ 42 | inline fun spy(stubbing: KStubbing.(T) -> Unit): T { 43 | return Mockito.spy(T::class.java) 44 | .apply { KStubbing(this).stubbing(this) }!! 45 | } 46 | 47 | /** 48 | * Creates a spy of the real object. The spy calls real methods unless they are stubbed. 49 | */ 50 | fun spy(value: T): T { 51 | return Mockito.spy(value)!! 52 | } 53 | 54 | /** 55 | * Creates a spy of the real object, allowing for immediate stubbing. 56 | * The spy calls real methods unless they are stubbed. 57 | */ 58 | inline fun spy(value: T, stubbing: KStubbing.(T) -> Unit): T { 59 | return spy(value) 60 | .apply { KStubbing(this).stubbing(this) } 61 | } 62 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Mockito-Kotlin 2 | 3 | [ ![Download](https://maven-badges.herokuapp.com/maven-central/org.mockito.kotlin/mockito-kotlin/badge.svg) ](https://maven-badges.herokuapp.com/maven-central/org.mockito.kotlin/mockito-kotlin) 4 | [![Nexus Snapshot](https://img.shields.io/nexus/s/org.mockito.kotlin/mockito-kotlin?server=https%3A%2F%2Fs01.oss.sonatype.org%2F)](https://s01.oss.sonatype.org/content/repositories/snapshots/org/mockito/kotlin/mockito-kotlin/) 5 | 6 | A small library that provides helper functions to work with [Mockito](https://github.com/mockito/mockito) in Kotlin. 7 | 8 | ## Install 9 | 10 | Mockito-Kotlin is available on Maven Central. 11 | For Gradle users, add the following to your `build.gradle`, replacing `x.x.x` with the latest version: 12 | 13 | ```groovy 14 | testImplementation "org.mockito.kotlin:mockito-kotlin:x.x.x" 15 | ``` 16 | 17 | ## Example 18 | 19 | A test using Mockito-Kotlin typically looks like the following: 20 | 21 | ```kotlin 22 | @Test 23 | fun doAction_doesSomething(){ 24 | /* Given */ 25 | val mock = mock { 26 | on { getText() } doReturn "text" 27 | } 28 | val classUnderTest = ClassUnderTest(mock) 29 | 30 | /* When */ 31 | classUnderTest.doAction() 32 | 33 | /* Then */ 34 | verify(mock).doSomething(any()) 35 | } 36 | ``` 37 | 38 | For more info and samples, see the [Wiki](https://github.com/mockito/mockito-kotlin/wiki). 39 | 40 | ## Building 41 | 42 | Mockito-Kotlin is built with Gradle. 43 | 44 | - `./gradlew build` builds and tests the project 45 | - `./gradlew publishToMavenLocal` installs the maven artifacts in your local repository 46 | - `./gradlew check` runs the test suite (See Testing below) 47 | 48 | ### Versioning 49 | 50 | Mockito-Kotlin roughly follows SEMVER 51 | 52 | ### Testing 53 | 54 | Mockito-Kotlin's test suite is located in a separate `tests` module, 55 | to allow running the tests using several Kotlin versions whilst still 56 | keeping the base module at a recent version. 57 | 58 | - `./gradlew check` runs the checks including tests. 59 | 60 | Usually it is enough to test only using the default Kotlin versions; 61 | CI will test against multiple versions. 62 | If you want to test using a different Kotlin version locally, 63 | add the `-PtestKotlinVersion=1.2.3` argument to the Gradle invocation while running the tests. 64 | 65 | ### Acknowledgements 66 | 67 | `mockito-kotlin` was created and developed by [nhaarman@](https://github.com/nhaarman) after which the repository was integrated into the official Mockito GitHub organization. 68 | We would like to thank Niek for the original idea and extensive work plus support that went into `mockito-kotlin`. 69 | -------------------------------------------------------------------------------- /mockito-kotlin/src/main/kotlin/org/mockito/kotlin/Stubber.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018 Niek Haarman 5 | * Copyright (c) 2007 Mockito contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | package org.mockito.kotlin 27 | 28 | import kotlinx.coroutines.runBlocking 29 | import org.mockito.Mockito 30 | import org.mockito.invocation.InvocationOnMock 31 | import org.mockito.stubbing.Stubber 32 | import kotlin.reflect.KClass 33 | 34 | fun doAnswer(answer: (InvocationOnMock) -> T?): Stubber { 35 | return Mockito.doAnswer { answer(it) }!! 36 | } 37 | 38 | fun doCallRealMethod(): Stubber { 39 | return Mockito.doCallRealMethod()!! 40 | } 41 | 42 | fun doNothing(): Stubber { 43 | return Mockito.doNothing()!! 44 | } 45 | 46 | fun doReturn(value: Any?): Stubber { 47 | return Mockito.doReturn(value)!! 48 | } 49 | 50 | fun doReturn(toBeReturned: Any?, vararg toBeReturnedNext: Any?): Stubber { 51 | return Mockito.doReturn( 52 | toBeReturned, 53 | *toBeReturnedNext 54 | )!! 55 | } 56 | 57 | fun doThrow(toBeThrown: KClass): Stubber { 58 | return Mockito.doThrow(toBeThrown.java)!! 59 | } 60 | 61 | fun doThrow(vararg toBeThrown: Throwable): Stubber { 62 | return Mockito.doThrow(*toBeThrown)!! 63 | } 64 | 65 | fun Stubber.whenever(mock: T) = `when`(mock) 66 | 67 | /** 68 | * Alias for when with suspending function 69 | * 70 | * Warning: Only one method call can be stubbed in the function. 71 | * Subsequent method calls are ignored! 72 | */ 73 | fun Stubber.wheneverBlocking(mock: T, f: suspend T.() -> Unit) { 74 | val m = whenever(mock) 75 | runBlocking { m.f() } 76 | } 77 | -------------------------------------------------------------------------------- /tests/src/test/kotlin/test/VerificationTest.kt: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import com.nhaarman.expect.expect 4 | import org.junit.Test 5 | import org.mockito.exceptions.base.MockitoAssertionError 6 | import org.mockito.kotlin.* 7 | import org.mockito.kotlin.verify 8 | 9 | class VerificationTest : TestBase() { 10 | 11 | @Test 12 | fun atLeastXInvocations() { 13 | mock().apply { 14 | string("") 15 | string("") 16 | 17 | verify(this, atLeast(2)).string(any()) 18 | } 19 | } 20 | 21 | @Test 22 | fun testAtLeastOnce() { 23 | mock().apply { 24 | string("") 25 | string("") 26 | 27 | verify(this, atLeastOnce()).string(any()) 28 | } 29 | } 30 | 31 | @Test 32 | fun atMostXInvocations() { 33 | mock().apply { 34 | string("") 35 | string("") 36 | 37 | verify(this, atMost(2)).string(any()) 38 | } 39 | } 40 | 41 | @Test 42 | fun testCalls() { 43 | mock().apply { 44 | string("") 45 | string("") 46 | 47 | inOrder(this).verify(this, calls(2)).string(any()) 48 | } 49 | } 50 | 51 | @Test 52 | fun testInOrderWithLambda() { 53 | /* Given */ 54 | val a = mock<() -> Unit>() 55 | val b = mock<() -> Unit>() 56 | 57 | /* When */ 58 | b() 59 | a() 60 | 61 | /* Then */ 62 | inOrder(a, b) { 63 | verify(b).invoke() 64 | verify(a).invoke() 65 | } 66 | } 67 | 68 | @Test 69 | fun testInOrderWithReceiver() { 70 | /* Given */ 71 | val mock = mock() 72 | 73 | /* When */ 74 | mock.string("") 75 | mock.int(0) 76 | 77 | /* Then */ 78 | mock.inOrder { 79 | verify().string(any()) 80 | verify().int(any()) 81 | verifyNoMoreInteractions() 82 | } 83 | } 84 | 85 | @Test 86 | fun testClearInvocations() { 87 | val mock = mock().apply { 88 | string("") 89 | } 90 | 91 | clearInvocations(mock) 92 | 93 | verify(mock, never()).string(any()) 94 | } 95 | 96 | @Test 97 | fun testDescription() { 98 | try { 99 | mock().apply { 100 | verify(this, description("Test")).string(any()) 101 | } 102 | throw AssertionError("Verify should throw Exception.") 103 | } catch (e: MockitoAssertionError) { 104 | expect(e.message).toContain("Test") 105 | } 106 | } 107 | 108 | @Test 109 | fun testAfter() { 110 | mock().apply { 111 | int(3) 112 | verify(this, after(10)).int(3) 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /tests/src/test/kotlin/test/AdditionalMatchersTest.kt: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import org.junit.Test 4 | import org.mockito.kotlin.* 5 | 6 | class AdditionalCaptorsTest : TestBase() { 7 | 8 | @Test 9 | fun testGeq() { 10 | mock().apply { 11 | int(1) 12 | verify(this).int(geq(0)) 13 | verify(this).int(geq(1)) 14 | verify(this, never()).int(geq(2)) 15 | } 16 | } 17 | 18 | @Test 19 | fun testLeq() { 20 | mock().apply { 21 | int(1) 22 | verify(this).int(leq(2)) 23 | verify(this).int(leq(1)) 24 | verify(this, never()).int(leq(0)) 25 | } 26 | } 27 | 28 | @Test 29 | fun testGt() { 30 | mock().apply { 31 | int(1) 32 | verify(this).int(gt(0)) 33 | verify(this, never()).int(gt(1)) 34 | } 35 | } 36 | 37 | @Test 38 | fun testLt() { 39 | mock().apply { 40 | int(1) 41 | verify(this).int(lt(2)) 42 | verify(this, never()).int(lt(1)) 43 | } 44 | } 45 | 46 | @Test 47 | fun testCmpEq() { 48 | mock().apply { 49 | int(1) 50 | verify(this).int(cmpEq(1)) 51 | verify(this, never()).int(cmpEq(2)) 52 | } 53 | } 54 | 55 | @Test 56 | fun testAryEqPrimitive() { 57 | mock().apply { 58 | intArray(intArrayOf(1, 2, 3)) 59 | verify(this).intArray(aryEq(intArrayOf(1, 2, 3))) 60 | verify(this, never()).intArray(aryEq(intArrayOf(1, 2))) 61 | } 62 | } 63 | 64 | @Test 65 | fun testAryEq() { 66 | mock().apply { 67 | stringArray(arrayOf("Hello", "there")) 68 | verify(this).stringArray(aryEq(arrayOf("Hello", "there"))) 69 | verify(this, never()).stringArray(aryEq(arrayOf("Hello"))) 70 | } 71 | } 72 | 73 | @Test 74 | fun testfind() { 75 | mock().apply { 76 | string("Hello") 77 | verify(this).string(find("l+o$".toRegex())) 78 | verify(this, never()).string(find("l$".toRegex())) 79 | } 80 | } 81 | 82 | @Test 83 | fun testAnd() { 84 | mock().apply { 85 | int(5) 86 | verify(this).int(and(geq(4), leq(6))) 87 | verify(this, never()).int(and(geq(4), leq(4))) 88 | } 89 | } 90 | 91 | @Test 92 | fun testOr() { 93 | mock().apply { 94 | int(5) 95 | verify(this).int(and(gt(4), lt(6))) 96 | verify(this, never()).int(and(gt(4), lt(4))) 97 | } 98 | } 99 | 100 | @Test 101 | fun testNot() { 102 | mock().apply { 103 | int(5) 104 | verify(this).int(not(eq(4))) 105 | verify(this, never()).int(not(eq(5))) 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /tests/src/test/kotlin/test/StubberTest.kt: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import com.nhaarman.expect.expect 4 | import com.nhaarman.expect.expectErrorWithMessage 5 | import org.junit.Test 6 | import org.mockito.kotlin.* 7 | 8 | class StubberTest : TestBase() { 9 | 10 | @Test 11 | fun testDoAnswer() { 12 | val mock = mock() 13 | 14 | doAnswer { "Test" } 15 | .whenever(mock) 16 | .stringResult() 17 | 18 | expect(mock.stringResult()).toBe("Test") 19 | } 20 | 21 | @Test 22 | fun testDoCallRealMethod() { 23 | val mock = mock() 24 | 25 | doReturn("Test").whenever(mock).stringResult() 26 | doCallRealMethod().whenever(mock).stringResult() 27 | 28 | expect(mock.stringResult()).toBe("Default") 29 | } 30 | 31 | @Test 32 | fun testDoNothing() { 33 | val spy = spy(Open()) 34 | val array = intArrayOf(3) 35 | 36 | doNothing().whenever(spy).modifiesContents(array) 37 | spy.modifiesContents(array) 38 | 39 | expect(array[0]).toBe(3) 40 | } 41 | 42 | @Test 43 | fun testDoReturnValue() { 44 | val mock = mock() 45 | 46 | doReturn("test").whenever(mock).stringResult() 47 | 48 | expect(mock.stringResult()).toBe("test") 49 | } 50 | 51 | @Test 52 | fun testDoReturnNullValue() { 53 | val mock = mock() 54 | 55 | doReturn(null).whenever(mock).stringResult() 56 | 57 | expect(mock.stringResult()).toBeNull() 58 | } 59 | 60 | @Test 61 | fun testDoReturnNullValues() { 62 | val mock = mock() 63 | 64 | doReturn(null, null).whenever(mock).stringResult() 65 | 66 | expect(mock.stringResult()).toBeNull() 67 | expect(mock.stringResult()).toBeNull() 68 | } 69 | 70 | @Test 71 | fun testDoReturnValues() { 72 | val mock = mock() 73 | 74 | doReturn("test", "test2").whenever(mock).stringResult() 75 | 76 | expect(mock.stringResult()).toBe("test") 77 | expect(mock.stringResult()).toBe("test2") 78 | } 79 | 80 | @Test 81 | fun testDoThrowClass() { 82 | val mock = mock() 83 | 84 | doThrow(IllegalStateException::class).whenever(mock).go() 85 | 86 | try { 87 | mock.go() 88 | throw AssertionError("Call should have thrown.") 89 | } catch (e: IllegalStateException) { 90 | } 91 | } 92 | 93 | @Test 94 | fun testDoThrow() { 95 | val mock = mock() 96 | 97 | doThrow(IllegalStateException("test")).whenever(mock).go() 98 | 99 | expectErrorWithMessage("test").on { 100 | mock.go() 101 | } 102 | } 103 | 104 | @Test 105 | fun testStubberOnBlockExtension() { 106 | val mock = mock { 107 | doReturn("Test").on { stringResult() } 108 | } 109 | 110 | expect(mock.stringResult()).toBe("Test") 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /tests/src/test/kotlin/test/EqTest.kt: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | /* 4 | * The MIT License 5 | * 6 | * Copyright (c) 2016 Niek Haarman 7 | * Copyright (c) 2007 Mockito contributors 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining a copy 10 | * of this software and associated documentation files (the "Software"), to deal 11 | * in the Software without restriction, including without limitation the rights 12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | * copies of the Software, and to permit persons to whom the Software is 14 | * furnished to do so, subject to the following conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be included in 17 | * all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | * THE SOFTWARE. 26 | */ 27 | 28 | import com.nhaarman.expect.expect 29 | import org.mockito.kotlin.eq 30 | import org.mockito.kotlin.mock 31 | import org.junit.After 32 | import org.junit.Before 33 | import org.junit.Test 34 | import org.mockito.Mockito 35 | 36 | class EqTest : TestBase() { 37 | 38 | private val interfaceInstance: MyInterface = MyClass() 39 | private val openClassInstance: MyClass = MyClass() 40 | private val closedClassInstance: ClosedClass = ClosedClass() 41 | 42 | private lateinit var doAnswer: Open 43 | 44 | @Before 45 | fun setup() { 46 | /* Create a proper Mockito state */ 47 | doAnswer = Mockito.doAnswer { }.`when`(mock()) 48 | } 49 | 50 | @After 51 | override fun tearDown() { 52 | super.tearDown() 53 | 54 | /* Close `any` Mockito state */ 55 | doAnswer.go(0) 56 | } 57 | 58 | @Test 59 | fun eqInterfaceInstance() { 60 | /* When */ 61 | val result = eq(interfaceInstance) 62 | 63 | /* Then */ 64 | expect(result).toNotBeNull() 65 | } 66 | 67 | @Test 68 | fun eqOpenClassInstance() { 69 | /* When */ 70 | val result = eq(openClassInstance) 71 | 72 | /* Then */ 73 | expect(result).toNotBeNull() 74 | } 75 | 76 | @Test 77 | fun eqClosedClassInstance() { 78 | /* When */ 79 | val result = eq(closedClassInstance) 80 | 81 | /* Then */ 82 | expect(result).toNotBeNull() 83 | } 84 | 85 | @Test 86 | fun nullArgument() { 87 | /* Given */ 88 | val s: String? = null 89 | 90 | /* When */ 91 | val result = eq(s) 92 | 93 | /* Then */ 94 | expect(result).toBeNull() 95 | } 96 | 97 | private interface MyInterface 98 | private open class MyClass : MyInterface 99 | class ClosedClass 100 | } 101 | 102 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | # 2 | # CI build that assembles artifacts and runs tests. 3 | # If validation is successful this workflow releases from the main dev branch. 4 | # 5 | # - skipping CI: add [skip ci] to the commit message 6 | # - skipping release: add [skip release] to the commit message 7 | # 8 | name: CI 9 | 10 | on: 11 | push: 12 | branches: 13 | - main 14 | tags: 15 | - 5.* 16 | pull_request: 17 | branches: 18 | - main 19 | 20 | jobs: 21 | 22 | # 23 | # SINGLE-JOB 24 | # 25 | verify: 26 | runs-on: ubuntu-latest 27 | if: "! contains(toJSON(github.event.commits.*.message), '[skip ci]')" 28 | 29 | steps: 30 | 31 | - name: 1. Check out code 32 | uses: actions/checkout@v2 # https://github.com/actions/checkout 33 | 34 | - name: 2. Set up Java 11 35 | uses: actions/setup-java@v1 # https://github.com/actions/setup-java 36 | with: 37 | java-version: 11 38 | 39 | - name: 3. Validate Gradle wrapper 40 | uses: gradle/wrapper-validation-action@v1 # https://github.com/gradle/wrapper-validation-action 41 | 42 | # 43 | # Main build job 44 | # 45 | build: 46 | needs: [verify] 47 | runs-on: ubuntu-latest 48 | 49 | # Definition of the build matrix 50 | strategy: 51 | matrix: 52 | mock-maker: ['mock-maker-default', 'mock-maker-inline'] 53 | kotlin: ['1.9.20'] 54 | # Note that the old Travis CI referenced other Kotlin versions: '1.0.7', '1.1.61', '1.2.50' 55 | # However, those versions of Kotlin don't work with latest Gradle 56 | 57 | steps: 58 | 59 | - name: 1. Check out code 60 | uses: actions/checkout@v2 # https://github.com/actions/checkout 61 | 62 | - name: 2. Set up Java 11 63 | uses: actions/setup-java@v1 # https://github.com/actions/setup-java 64 | with: 65 | java-version: 11 66 | 67 | - name: 3. Build with Kotlin ${{ matrix.kotlin }} and mock-maker ${{ matrix.mock-maker }} 68 | run: | 69 | ops/mockMakerInline.sh 70 | ./gradlew build -PtestKotlinVersion=${{ matrix.kotlin }} 71 | env: 72 | MOCK_MAKER: ${{ matrix.mock-maker }} 73 | 74 | # 75 | # Release job, only for pushes to the main development branch 76 | # 77 | release: 78 | runs-on: ubuntu-latest 79 | needs: [build] # build job must pass before we can release 80 | 81 | if: github.event_name == 'push' 82 | && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/5.')) 83 | && github.repository == 'mockito/mockito-kotlin' 84 | && !contains(toJSON(github.event.commits.*.message), '[skip release]') 85 | 86 | steps: 87 | 88 | - name: Check out code 89 | uses: actions/checkout@v2 # https://github.com/actions/checkout 90 | with: 91 | fetch-depth: '0' # https://github.com/shipkit/shipkit-changelog#fetch-depth-on-ci 92 | 93 | - name: Set up Java 11 94 | uses: actions/setup-java@v1 95 | with: 96 | java-version: 11 97 | 98 | - name: Build and release 99 | run: ./gradlew githubRelease publishToSonatype closeAndReleaseStagingRepository releaseSummary 100 | env: 101 | GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} 102 | NEXUS_TOKEN_USER: ${{secrets.NEXUS_TOKEN_USER}} 103 | NEXUS_TOKEN_PWD: ${{secrets.NEXUS_TOKEN_PWD}} 104 | PGP_KEY: ${{secrets.PGP_KEY}} 105 | PGP_PWD: ${{secrets.PGP_PWD}} 106 | -------------------------------------------------------------------------------- /mockito-kotlin/src/test/kotlin/org/mockito/kotlin/BDDMockitoKtTest.kt: -------------------------------------------------------------------------------- 1 | package org.mockito.kotlin 2 | 3 | import kotlinx.coroutines.Dispatchers 4 | import kotlinx.coroutines.runBlocking 5 | import kotlinx.coroutines.withContext 6 | import org.junit.Assert.assertEquals 7 | import org.junit.Test 8 | import kotlin.test.assertFailsWith 9 | 10 | class BDDMockitoKtTest { 11 | 12 | @Test 13 | fun willSuspendableAnswer_withoutArgument() = runBlocking { 14 | val fixture: SomeInterface = mock() 15 | 16 | given(fixture.suspending()).willSuspendableAnswer { 17 | withContext(Dispatchers.Default) { 42 } 18 | } 19 | 20 | assertEquals(42, fixture.suspending()) 21 | then(fixture).should().suspending() 22 | Unit 23 | } 24 | 25 | @Test 26 | fun willSuspendableAnswer_withArgument() = runBlocking { 27 | val fixture: SomeInterface = mock() 28 | 29 | given(fixture.suspendingWithArg(any())).willSuspendableAnswer { 30 | withContext(Dispatchers.Default) { it.getArgument(0) } 31 | } 32 | 33 | assertEquals(42, fixture.suspendingWithArg(42)) 34 | then(fixture).should().suspendingWithArg(42) 35 | Unit 36 | } 37 | 38 | @Test 39 | fun willSuspendableAnswer_givenBlocking() { 40 | val fixture: SomeInterface = mock() 41 | 42 | givenBlocking { fixture.suspending() }.willSuspendableAnswer { 43 | withContext(Dispatchers.Default) { 42 } 44 | } 45 | 46 | val result = runBlocking { 47 | fixture.suspending() 48 | } 49 | 50 | assertEquals(42, result) 51 | then(fixture).shouldBlocking { suspending() } 52 | Unit 53 | } 54 | 55 | @Test 56 | fun willSuspendableAnswer_givenBlocking_withArgument() { 57 | val fixture: SomeInterface = mock() 58 | 59 | givenBlocking { fixture.suspendingWithArg(any()) }.willSuspendableAnswer { 60 | withContext(Dispatchers.Default) { it.getArgument(0) } 61 | } 62 | 63 | val result = runBlocking { 64 | fixture.suspendingWithArg(42) 65 | } 66 | 67 | assertEquals(42, result) 68 | then(fixture).shouldBlocking { suspendingWithArg(42) } 69 | Unit 70 | } 71 | 72 | @Test 73 | fun willThrow_kclass_single() { 74 | val fixture: SomeInterface = mock() 75 | 76 | given(fixture.foo()).willThrow(RuntimeException::class) 77 | 78 | assertFailsWith(RuntimeException::class) { 79 | fixture.foo() 80 | } 81 | } 82 | 83 | @Test 84 | fun willThrow_kclass_multiple() { 85 | val fixture: SomeInterface = mock() 86 | 87 | given(fixture.foo()).willThrow(RuntimeException::class, IllegalArgumentException::class) 88 | 89 | assertFailsWith(RuntimeException::class) { 90 | fixture.foo() 91 | } 92 | assertFailsWith(IllegalArgumentException::class) { 93 | fixture.foo() 94 | } 95 | } 96 | 97 | @Test 98 | fun willReturnConsecutively() { 99 | val fixture: SomeInterface = mock() 100 | 101 | given(fixture.foo()).willReturnConsecutively(listOf(42, 24)) 102 | 103 | assertEquals(42, fixture.foo()) 104 | assertEquals(24, fixture.foo()) 105 | } 106 | } 107 | 108 | interface SomeInterface { 109 | fun foo(): Int 110 | 111 | suspend fun suspending(): Int 112 | suspend fun suspendingWithArg(arg: Int): Int 113 | } 114 | -------------------------------------------------------------------------------- /tests/src/test/kotlin/test/Classes.kt: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | /* 4 | * The MIT License 5 | * 6 | * Copyright (c) 2016 Niek Haarman 7 | * Copyright (c) 2007 Mockito contributors 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining a copy 10 | * of this software and associated documentation files (the "Software"), to deal 11 | * in the Software without restriction, including without limitation the rights 12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | * copies of the Software, and to permit persons to whom the Software is 14 | * furnished to do so, subject to the following conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be included in 17 | * all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | * THE SOFTWARE. 26 | */ 27 | 28 | open class Open { 29 | open fun go(vararg arg: Any?) { 30 | } 31 | 32 | open fun modifiesContents(a: IntArray) { 33 | for (i in 0..a.size - 1) { 34 | a[i] = a[i] + 1 35 | } 36 | } 37 | 38 | open fun stringResult() = "Default" 39 | 40 | fun throwsNPE(): Any = throw NullPointerException("Test") 41 | } 42 | 43 | class Closed 44 | 45 | interface Methods { 46 | 47 | fun intArray(i: IntArray) 48 | fun closed(c: Closed) 49 | fun closedArray(a: Array) 50 | fun closedNullableArray(a: Array) 51 | fun closedCollection(c: Collection) 52 | fun closedList(c: List) 53 | fun closedStringMap(m: Map) 54 | fun closedSet(s: Set) 55 | fun string(s: String) 56 | fun boolean(b: Boolean) 57 | fun byte(b: Byte) 58 | fun char(c: Char) 59 | fun short(s: Short) 60 | fun int(i: Int) 61 | fun long(l: Long) 62 | fun float(f: Float) 63 | fun double(d: Double) 64 | fun closedVararg(vararg c: Closed) 65 | fun throwableClass(t: ThrowableClass) 66 | fun nullableString(s: String?) 67 | 68 | fun stringResult(): String 69 | fun stringResult(s: String): String 70 | fun nullableStringResult(): String? 71 | fun builderMethod(): Methods 72 | fun varargBooleanResult(vararg values: String): Boolean 73 | fun stringArray(a: Array) 74 | fun argAndVararg(s: String, vararg a: String) 75 | 76 | fun nonDefaultReturnType(): ExtraInterface 77 | } 78 | 79 | interface ExtraInterface 80 | 81 | abstract class ThrowingConstructor { 82 | 83 | constructor() { 84 | error("Error in constructor") 85 | } 86 | } 87 | 88 | abstract class ThrowingConstructorWithArgument { 89 | 90 | constructor(s: String) { 91 | error("Error in constructor: $s") 92 | } 93 | } 94 | 95 | abstract class NonThrowingConstructorWithArgument { 96 | 97 | constructor() { 98 | error("Error in constructor") 99 | } 100 | 101 | @Suppress("UNUSED_PARAMETER") 102 | constructor(s: String) 103 | } 104 | 105 | interface GenericMethods { 106 | fun genericMethod(): T 107 | fun nullableReturnType(): T? 108 | } 109 | 110 | class ThrowableClass(cause: Throwable) : Throwable(cause) 111 | -------------------------------------------------------------------------------- /tests/src/test/kotlin/test/BDDMockitoTest.kt: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import com.nhaarman.expect.expect 4 | import org.junit.Test 5 | import org.mockito.kotlin.* 6 | import org.mockito.stubbing.Answer 7 | 8 | class BDDMockitoTest { 9 | 10 | @Test 11 | fun given_will_properlyStubs() { 12 | /* Given */ 13 | val mock = mock() 14 | 15 | /* When */ 16 | given(mock.stringResult()) will Answer { "Test" } 17 | 18 | /* Then */ 19 | expect(mock.stringResult()).toBe("Test") 20 | } 21 | 22 | @Test 23 | fun given_willReturn_properlyStubs() { 24 | /* Given */ 25 | val mock = mock() 26 | 27 | /* When */ 28 | given(mock.stringResult()).willReturn("Test") 29 | 30 | /* Then */ 31 | expect(mock.stringResult()).toBe("Test") 32 | } 33 | 34 | @Test 35 | fun givenLambda_willReturn_properlyStubs() { 36 | /* Given */ 37 | val mock = mock() 38 | 39 | /* When */ 40 | given { mock.stringResult() }.willReturn("Test") 41 | 42 | /* Then */ 43 | expect(mock.stringResult()).toBe("Test") 44 | } 45 | 46 | @Test 47 | fun given_willReturnLambda_properlyStubs() { 48 | /* Given */ 49 | val mock = mock() 50 | 51 | /* When */ 52 | given(mock.stringResult()).willReturn { "Test" } 53 | 54 | /* Then */ 55 | expect(mock.stringResult()).toBe("Test") 56 | } 57 | 58 | @Test 59 | fun givenLambda_willReturnLambda_properlyStubs() { 60 | /* Given */ 61 | val mock = mock() 62 | 63 | /* When */ 64 | given { mock.stringResult() } willReturn { "Test" } 65 | 66 | /* Then */ 67 | expect(mock.stringResult()).toBe("Test") 68 | } 69 | 70 | @Test 71 | fun given_willAnswer_properlyStubs() { 72 | /* Given */ 73 | val mock = mock() 74 | 75 | /* When */ 76 | given(mock.stringResult()).willAnswer { "Test" } 77 | 78 | /* Then */ 79 | expect(mock.stringResult()).toBe("Test") 80 | } 81 | 82 | @Test 83 | fun given_willAnswerInfix_properlyStubs() { 84 | /* Given */ 85 | val mock = mock() 86 | 87 | /* When */ 88 | given(mock.stringResult()) willAnswer { "Test" } 89 | 90 | /* Then */ 91 | expect(mock.stringResult()).toBe("Test") 92 | } 93 | 94 | @Test 95 | fun given_willAnswerInfix_withInvocationInfo_properlyStubs() { 96 | /* Given */ 97 | val mock = mock() 98 | 99 | /* When */ 100 | given(mock.stringResult(any())) willAnswer { invocation -> 101 | (invocation.arguments[0] as String) 102 | .reversed() 103 | } 104 | 105 | /* Then */ 106 | expect(mock.stringResult("Test")).toBe("tseT") 107 | } 108 | 109 | @Test(expected = IllegalStateException::class) 110 | fun given_willThrowInfix_properlyStubs() { 111 | /* Given */ 112 | val mock = mock() 113 | 114 | /* When */ 115 | given(mock.stringResult()) willThrow { IllegalStateException() } 116 | mock.stringResult() 117 | } 118 | 119 | @Test 120 | fun then() { 121 | /* Given */ 122 | val mock = mock() 123 | whenever(mock.stringResult()).thenReturn("Test") 124 | 125 | /* When */ 126 | mock.stringResult() 127 | 128 | /* Then */ 129 | org.mockito.kotlin.then(mock).should().stringResult() 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /tests/src/test/kotlin/test/inline/UsingMockMakerInlineTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2016 Ian J. De Silva 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | import com.nhaarman.expect.expect 26 | import org.junit.Assume.assumeTrue 27 | import org.junit.Before 28 | import org.junit.Test 29 | import org.mockito.kotlin.* 30 | import test.mockMakerInlineEnabled 31 | import java.io.IOException 32 | import java.math.BigInteger 33 | 34 | class UsingMockMakerInlineTest { 35 | 36 | class ClassToBeMocked { 37 | 38 | fun doSomething(@Suppress("UNUSED_PARAMETER") c: ClassToBeMocked) { 39 | } 40 | 41 | fun doSomethingElse(value: BigInteger): BigInteger { 42 | return value.plus(BigInteger.ONE) 43 | } 44 | } 45 | 46 | @Before 47 | fun setup() { 48 | mockMakerInlineEnabled = null 49 | assumeTrue(mockMakerInlineEnabled()) 50 | } 51 | 52 | @Test 53 | fun mockClosedClass() { 54 | /* When */ 55 | val result = mock() 56 | 57 | /* Then */ 58 | expect(result).toNotBeNull() 59 | } 60 | 61 | @Test 62 | fun anyClosedClass() { 63 | /* Given */ 64 | val mock = mock() 65 | 66 | /* When */ 67 | mock.doSomething(mock) 68 | 69 | /* Then */ 70 | verify(mock).doSomething(any()) 71 | } 72 | 73 | @Test 74 | fun mockClosedFunction_mockStubbing() { 75 | /* Given */ 76 | val mock = mock { 77 | on { doSomethingElse(any()) } doReturn (BigInteger.ONE) 78 | } 79 | 80 | /* When */ 81 | val result = mock.doSomethingElse(BigInteger.TEN) 82 | 83 | /* Then */ 84 | expect(result).toBe(BigInteger.ONE) 85 | } 86 | 87 | @Test 88 | fun mockClosedFunction_whenever() { 89 | /* Given */ 90 | val mock = mock() 91 | whenever(mock.doSomethingElse(any())).doReturn(BigInteger.ONE) 92 | 93 | /* When */ 94 | val result = mock.doSomethingElse(BigInteger.TEN) 95 | 96 | /* Then */ 97 | expect(result).toBe(BigInteger.ONE) 98 | } 99 | 100 | /** https://github.com/nhaarman/mockito-kotlin/issues/27 */ 101 | @Test 102 | fun anyThrowableWithSingleThrowableConstructor() { 103 | mock().apply { 104 | throwableClass(ThrowableClass(IOException())) 105 | verify(this).throwableClass(any()) 106 | } 107 | } 108 | 109 | interface Methods { 110 | 111 | fun throwableClass(t: ThrowableClass) 112 | } 113 | 114 | class ThrowableClass(cause: Throwable) : Throwable(cause) 115 | 116 | } 117 | -------------------------------------------------------------------------------- /mockito-kotlin/src/main/kotlin/org/mockito/kotlin/KStubbing.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018 Niek Haarman 5 | * Copyright (c) 2007 Mockito contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | package org.mockito.kotlin 27 | 28 | import org.mockito.kotlin.internal.createInstance 29 | import kotlinx.coroutines.runBlocking 30 | import org.mockito.Mockito 31 | import org.mockito.exceptions.misusing.NotAMockException 32 | import org.mockito.stubbing.OngoingStubbing 33 | import org.mockito.stubbing.Stubber 34 | import kotlin.reflect.KClass 35 | 36 | inline fun stubbing( 37 | mock: T, 38 | stubbing: KStubbing.(T) -> Unit 39 | ) { 40 | KStubbing(mock).stubbing(mock) 41 | } 42 | 43 | inline fun T.stub(stubbing: KStubbing.(T) -> Unit): T { 44 | return apply { KStubbing(this).stubbing(this) } 45 | } 46 | 47 | class KStubbing(val mock: T) { 48 | init { 49 | if (!mockingDetails(mock).isMock) throw NotAMockException("Stubbing target is not a mock!") 50 | } 51 | 52 | fun on(methodCall: R): OngoingStubbing = Mockito.`when`(methodCall) 53 | 54 | fun onGeneric(methodCall: T.() -> R?, c: KClass): OngoingStubbing { 55 | val r = try { 56 | mock.methodCall() 57 | } catch (e: NullPointerException) { 58 | // An NPE may be thrown by the Kotlin type system when the MockMethodInterceptor returns a 59 | // null value for a non-nullable generic type. 60 | // We catch this NPE to return a valid instance. 61 | // The Mockito state has already been modified at this point to reflect 62 | // the wanted changes. 63 | createInstance(c) 64 | } 65 | return Mockito.`when`(r) 66 | } 67 | 68 | inline fun onGeneric(noinline methodCall: T.() -> R?): OngoingStubbing { 69 | return onGeneric(methodCall, R::class) 70 | } 71 | 72 | fun on(methodCall: T.() -> R): OngoingStubbing { 73 | return try { 74 | Mockito.`when`(mock.methodCall()) 75 | } catch (e: NullPointerException) { 76 | throw MockitoKotlinException( 77 | "NullPointerException thrown when stubbing.\nThis may be due to two reasons:\n\t- The method you're trying to stub threw an NPE: look at the stack trace below;\n\t- You're trying to stub a generic method: try `onGeneric` instead.", 78 | e 79 | ) 80 | } 81 | } 82 | 83 | fun KStubbing.onBlocking( 84 | m: suspend T.() -> R 85 | ): OngoingStubbing { 86 | return runBlocking { Mockito.`when`(mock.m()) } 87 | } 88 | 89 | fun Stubber.on(methodCall: T.() -> Unit) { 90 | this.`when`(mock).methodCall() 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /tests/src/test/kotlin/test/SpyTest.kt: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | /* 4 | * The MIT License 5 | * 6 | * Copyright (c) 2016 Niek Haarman 7 | * Copyright (c) 2007 Mockito contributors 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining a copy 10 | * of this software and associated documentation files (the "Software"), to deal 11 | * in the Software without restriction, including without limitation the rights 12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | * copies of the Software, and to permit persons to whom the Software is 14 | * furnished to do so, subject to the following conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be included in 17 | * all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | * THE SOFTWARE. 26 | */ 27 | 28 | import com.nhaarman.expect.expect 29 | import org.junit.After 30 | import org.junit.Test 31 | import org.mockito.Mockito 32 | import org.mockito.kotlin.* 33 | import java.util.* 34 | 35 | class SpyTest : TestBase() { 36 | 37 | private val interfaceInstance: MyInterface = MyClass() 38 | private val openClassInstance: MyClass = MyClass() 39 | private val closedClassInstance: ClosedClass = ClosedClass() 40 | 41 | @After 42 | override fun tearDown() { 43 | super.tearDown() 44 | Mockito.validateMockitoUsage() 45 | } 46 | 47 | @Test 48 | fun spyInterfaceInstance() { 49 | /* When */ 50 | val result = spy(interfaceInstance) 51 | 52 | /* Then */ 53 | expect(result).toNotBeNull() 54 | } 55 | 56 | @Test 57 | fun spyOpenClassInstance() { 58 | /* When */ 59 | val result = spy(openClassInstance) 60 | 61 | /* Then */ 62 | expect(result).toNotBeNull() 63 | } 64 | 65 | @Test 66 | fun doReturnWithSpy() { 67 | val date = spy(Date()) 68 | doReturn(123L).whenever(date).time 69 | expect(date.time).toBe(123L) 70 | } 71 | 72 | @Test 73 | fun doNothingWithSpy() { 74 | val date = spy(Date(0)) 75 | doNothing().whenever(date).time = 5L 76 | date.time = 5L 77 | expect(date.time).toBe(0L) 78 | } 79 | 80 | @Test(expected = IllegalArgumentException::class) 81 | fun doThrowWithSpy() { 82 | val date = spy(Date(0)) 83 | doThrow(IllegalArgumentException()).whenever(date).time 84 | date.time 85 | } 86 | 87 | @Test 88 | fun doCallRealMethodWithSpy() { 89 | val date = spy(Date(0)) 90 | doReturn(123L).whenever(date).time 91 | doCallRealMethod().whenever(date).time 92 | expect(date.time).toBe(0L) 93 | } 94 | 95 | @Test 96 | fun doReturnWithDefaultInstanceSpyStubbing() { 97 | val timeVal = 12L 98 | 99 | val dateSpy = spy { 100 | on { time } doReturn timeVal 101 | } 102 | 103 | expect(dateSpy.time).toBe(timeVal) 104 | } 105 | 106 | @Test 107 | fun doReturnWithSpyStubbing() { 108 | val timeVal = 15L 109 | 110 | val dateSpy = spy(Date(0)) { 111 | on { time } doReturn timeVal 112 | } 113 | 114 | expect(dateSpy.time).toBe(timeVal) 115 | } 116 | 117 | @Test 118 | fun passAnyStringToSpy() { 119 | /* Given */ 120 | val my = spy(MyClass()) 121 | 122 | /* When */ 123 | doReturn("mocked").whenever(my).foo(any()) 124 | 125 | /* Then */ 126 | expect(my.foo("hello")).toBe("mocked") 127 | } 128 | 129 | private interface MyInterface { 130 | 131 | fun foo(value: String): String 132 | } 133 | 134 | private open class MyClass : MyInterface { 135 | 136 | override fun foo(value: String): String = value 137 | } 138 | 139 | private class ClosedClass 140 | } 141 | 142 | -------------------------------------------------------------------------------- /mockito-kotlin/src/main/kotlin/org/mockito/kotlin/OngoingStubbing.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018 Niek Haarman 5 | * Copyright (c) 2007 Mockito contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | package org.mockito.kotlin 27 | 28 | import kotlinx.coroutines.CoroutineScope 29 | import kotlinx.coroutines.runBlocking 30 | import org.mockito.Mockito 31 | import org.mockito.invocation.InvocationOnMock 32 | import org.mockito.kotlin.internal.SuspendableAnswer 33 | import org.mockito.stubbing.Answer 34 | import org.mockito.stubbing.OngoingStubbing 35 | import kotlin.reflect.KClass 36 | 37 | /** 38 | * Enables stubbing methods. Use it when you want the mock to return particular value when particular method is called. 39 | * 40 | * Alias for [Mockito.when]. 41 | */ 42 | @Suppress("NOTHING_TO_INLINE") 43 | inline fun whenever(methodCall: T): OngoingStubbing { 44 | return Mockito.`when`(methodCall)!! 45 | } 46 | 47 | /** 48 | * Enables stubbing suspending methods. Use it when you want the mock to return particular value when particular suspending method is called. 49 | * 50 | * Warning: Only one method call can be stubbed in the function. 51 | * other method calls are ignored! 52 | */ 53 | fun wheneverBlocking(methodCall: suspend CoroutineScope.() -> T): OngoingStubbing { 54 | return runBlocking { Mockito.`when`(methodCall()) } 55 | } 56 | 57 | /** 58 | * Sets a return value to be returned when the method is called. 59 | * 60 | * Alias for [OngoingStubbing.thenReturn]. 61 | */ 62 | infix fun OngoingStubbing.doReturn(t: T): OngoingStubbing { 63 | return thenReturn(t) 64 | } 65 | 66 | /** 67 | * Sets consecutive return values to be returned when the method is called. 68 | * 69 | * Alias for [OngoingStubbing.thenReturn]. 70 | */ 71 | fun OngoingStubbing.doReturn(t: T, vararg ts: T): OngoingStubbing { 72 | return thenReturn(t, *ts) 73 | } 74 | 75 | /** 76 | * Sets consecutive return values to be returned when the method is called. 77 | */ 78 | inline infix fun OngoingStubbing.doReturnConsecutively(ts: List): OngoingStubbing { 79 | return thenReturn( 80 | ts[0], 81 | *ts.drop(1).toTypedArray() 82 | ) 83 | } 84 | 85 | /** 86 | * Sets Throwable objects to be thrown when the method is called. 87 | * 88 | * Alias for [OngoingStubbing.thenThrow]. 89 | */ 90 | infix fun OngoingStubbing.doThrow(t: Throwable): OngoingStubbing { 91 | return thenThrow(t) 92 | } 93 | 94 | /** 95 | * Sets Throwable objects to be thrown when the method is called. 96 | * 97 | * Alias for [OngoingStubbing.doThrow]. 98 | */ 99 | fun OngoingStubbing.doThrow( 100 | t: Throwable, 101 | vararg ts: Throwable 102 | ): OngoingStubbing { 103 | return thenThrow(t, *ts) 104 | } 105 | 106 | /** 107 | * Sets a Throwable type to be thrown when the method is called. 108 | */ 109 | infix fun OngoingStubbing.doThrow(t: KClass): OngoingStubbing { 110 | return thenThrow(t.java) 111 | } 112 | 113 | /** 114 | * Sets Throwable classes to be thrown when the method is called. 115 | */ 116 | fun OngoingStubbing.doThrow( 117 | t: KClass, 118 | vararg ts: KClass 119 | ): OngoingStubbing { 120 | return thenThrow(t.java, *ts.map { it.java }.toTypedArray()) 121 | } 122 | 123 | /** 124 | * Sets a generic Answer for the method. 125 | * 126 | * Alias for [OngoingStubbing.thenAnswer]. 127 | */ 128 | infix fun OngoingStubbing.doAnswer(answer: Answer<*>): OngoingStubbing { 129 | return thenAnswer(answer) 130 | } 131 | 132 | /** 133 | * Sets a generic Answer for the method using a lambda. 134 | */ 135 | infix fun OngoingStubbing.doAnswer(answer: (InvocationOnMock) -> T?): OngoingStubbing { 136 | return thenAnswer(answer) 137 | } 138 | 139 | infix fun OngoingStubbing.doSuspendableAnswer(answer: suspend (InvocationOnMock) -> T?): OngoingStubbing { 140 | return thenAnswer(SuspendableAnswer(answer)) 141 | } 142 | -------------------------------------------------------------------------------- /mockito-kotlin/src/main/kotlin/org/mockito/kotlin/BDDMockito.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018 Niek Haarman 5 | * Copyright (c) 2007 Mockito contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | package org.mockito.kotlin 27 | 28 | import kotlinx.coroutines.CoroutineScope 29 | import kotlinx.coroutines.runBlocking 30 | import org.mockito.BDDMockito 31 | import org.mockito.BDDMockito.BDDMyOngoingStubbing 32 | import org.mockito.BDDMockito.Then 33 | import org.mockito.invocation.InvocationOnMock 34 | import org.mockito.kotlin.internal.SuspendableAnswer 35 | import org.mockito.stubbing.Answer 36 | import kotlin.reflect.KClass 37 | 38 | /** 39 | * Alias for [BDDMockito.given]. 40 | */ 41 | fun given(methodCall: T): BDDMockito.BDDMyOngoingStubbing { 42 | return BDDMockito.given(methodCall) 43 | } 44 | 45 | /** 46 | * Alias for [BDDMockito.given] with a lambda. 47 | */ 48 | fun given(methodCall: () -> T): BDDMyOngoingStubbing { 49 | return given(methodCall()) 50 | } 51 | 52 | /** 53 | * Alias for [BDDMockito.given] with a suspending lambda 54 | * 55 | * Warning: Only last method call can be stubbed in the function. 56 | * other method calls are ignored! 57 | */ 58 | fun givenBlocking(methodCall: suspend CoroutineScope.() -> T): BDDMockito.BDDMyOngoingStubbing { 59 | return runBlocking { BDDMockito.given(methodCall()) } 60 | } 61 | 62 | /** 63 | * Alias for [BDDMockito.then]. 64 | */ 65 | fun then(mock: T): BDDMockito.Then { 66 | return BDDMockito.then(mock) 67 | } 68 | 69 | /** 70 | * Alias for [Then.should], with suspending lambda. 71 | */ 72 | fun Then.shouldBlocking(f: suspend T.() -> R): R { 73 | val m = should() 74 | return runBlocking { m.f() } 75 | } 76 | 77 | /** 78 | * Alias for [BDDMyOngoingStubbing.will] 79 | * */ 80 | infix fun BDDMyOngoingStubbing.will(value: Answer): BDDMockito.BDDMyOngoingStubbing { 81 | return will(value) 82 | } 83 | 84 | /** 85 | * Alias for [BBDMyOngoingStubbing.willAnswer], accepting a lambda. 86 | */ 87 | infix fun BDDMyOngoingStubbing.willAnswer(value: (InvocationOnMock) -> T?): BDDMockito.BDDMyOngoingStubbing { 88 | return willAnswer { value(it) } 89 | } 90 | 91 | /** 92 | * Alias for [BBDMyOngoingStubbing.willAnswer], accepting a suspend lambda. 93 | */ 94 | infix fun BDDMyOngoingStubbing.willSuspendableAnswer(value: suspend (InvocationOnMock) -> T?): BDDMockito.BDDMyOngoingStubbing { 95 | return willAnswer(SuspendableAnswer(value)) 96 | } 97 | 98 | /** 99 | * Alias for [BBDMyOngoingStubbing.willReturn]. 100 | */ 101 | infix fun BDDMyOngoingStubbing.willReturn(value: () -> T): BDDMockito.BDDMyOngoingStubbing { 102 | return willReturn(value()) 103 | } 104 | 105 | /** 106 | * Alias for [BBDMyOngoingStubbing.willThrow]. 107 | */ 108 | infix fun BDDMyOngoingStubbing.willThrow(value: () -> Throwable): BDDMockito.BDDMyOngoingStubbing { 109 | return willThrow(value()) 110 | } 111 | 112 | /** 113 | * Sets a Throwable type to be thrown when the method is called. 114 | * 115 | * Alias for [BDDMyOngoingStubbing.willThrow] 116 | */ 117 | infix fun BDDMyOngoingStubbing.willThrow(t: KClass): BDDMyOngoingStubbing { 118 | return willThrow(t.java) 119 | } 120 | 121 | /** 122 | * Sets Throwable classes to be thrown when the method is called. 123 | * 124 | * Alias for [BDDMyOngoingStubbing.willThrow] 125 | */ 126 | fun BDDMyOngoingStubbing.willThrow( 127 | t: KClass, 128 | vararg ts: KClass 129 | ): BDDMyOngoingStubbing { 130 | return willThrow(t.java, *ts.map { it.java }.toTypedArray()) 131 | } 132 | 133 | /** 134 | * Sets consecutive return values to be returned when the method is called. 135 | * Same as [BDDMyOngoingStubbing.willReturn], but accepts list instead of varargs. 136 | */ 137 | inline infix fun BDDMyOngoingStubbing.willReturnConsecutively(ts: List): BDDMyOngoingStubbing { 138 | return willReturn( 139 | ts[0], 140 | *ts.drop(1).toTypedArray() 141 | ) 142 | } 143 | -------------------------------------------------------------------------------- /mockito-kotlin/src/main/kotlin/org/mockito/kotlin/Matchers.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018 Niek Haarman 5 | * Copyright (c) 2007 Mockito contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | package org.mockito.kotlin 27 | 28 | import org.mockito.ArgumentMatcher 29 | import org.mockito.ArgumentMatchers 30 | import org.mockito.kotlin.internal.createInstance 31 | import kotlin.reflect.KClass 32 | 33 | /** Object argument that is equal to the given value. */ 34 | fun eq(value: T): T { 35 | return ArgumentMatchers.eq(value) ?: value 36 | } 37 | 38 | /** Object argument that is the same as the given value. */ 39 | fun same(value: T): T { 40 | return ArgumentMatchers.same(value) ?: value 41 | } 42 | 43 | /** Matches any object, excluding nulls. */ 44 | inline fun any(): T { 45 | return ArgumentMatchers.any(T::class.java) ?: createInstance() 46 | } 47 | 48 | /** Matches anything, including nulls. */ 49 | inline fun anyOrNull(): T { 50 | return ArgumentMatchers.any() ?: createInstance() 51 | } 52 | 53 | /** Matches any vararg object, including nulls. */ 54 | inline fun anyVararg(): T { 55 | return anyVararg(T::class) 56 | } 57 | 58 | fun anyVararg(clazz: KClass): T { 59 | return ArgumentMatchers.argThat(VarargMatcher(clazz.java)) ?: createInstance(clazz) 60 | } 61 | 62 | private class VarargMatcher(private val clazz: Class) : ArgumentMatcher { 63 | override fun matches(t: T): Boolean = true 64 | 65 | // In Java >= 12 you can do clazz.arrayClass() 66 | override fun type(): Class<*> = java.lang.reflect.Array.newInstance(clazz, 0).javaClass 67 | } 68 | 69 | /** Matches any array of type T. */ 70 | inline fun anyArray(): Array { 71 | return ArgumentMatchers.any(Array::class.java) ?: arrayOf() 72 | } 73 | 74 | /** 75 | * Creates a custom argument matcher. 76 | * `null` values will never evaluate to `true`. 77 | * 78 | * @param predicate An extension function on [T] that returns `true` when a [T] matches the predicate. 79 | */ 80 | inline fun argThat(noinline predicate: T.() -> Boolean): T { 81 | return ArgumentMatchers.argThat { arg: T? -> arg?.predicate() ?: false } ?: createInstance( 82 | T::class 83 | ) 84 | } 85 | 86 | /** 87 | * Registers a custom ArgumentMatcher. The original Mockito function registers the matcher and returns null, 88 | * here the required type is returned. 89 | * 90 | * @param matcher The ArgumentMatcher on [T] to be registered. 91 | */ 92 | inline fun argThat(matcher: ArgumentMatcher): T { 93 | return ArgumentMatchers.argThat(matcher) ?: createInstance() 94 | } 95 | 96 | /** 97 | * Alias for [argThat]. 98 | * 99 | * Creates a custom argument matcher. 100 | * `null` values will never evaluate to `true`. 101 | * 102 | * @param predicate An extension function on [T] that returns `true` when a [T] matches the predicate. 103 | */ 104 | inline fun argForWhich(noinline predicate: T.() -> Boolean): T { 105 | return argThat(predicate) 106 | } 107 | 108 | /** 109 | * Creates a custom argument matcher. 110 | * `null` values will never evaluate to `true`. 111 | * 112 | * @param predicate A function that returns `true` when given [T] matches the predicate. 113 | */ 114 | inline fun argWhere(noinline predicate: (T) -> Boolean): T { 115 | return argThat(predicate) 116 | } 117 | 118 | /** 119 | * Argument that implements the given class. 120 | */ 121 | inline fun isA(): T { 122 | return ArgumentMatchers.isA(T::class.java) ?: createInstance() 123 | } 124 | 125 | /** 126 | * `null` argument. 127 | */ 128 | fun isNull(): T? = ArgumentMatchers.isNull() 129 | 130 | /** 131 | * Not `null` argument. 132 | */ 133 | fun isNotNull(): T? { 134 | return ArgumentMatchers.isNotNull() 135 | } 136 | 137 | /** 138 | * Not `null` argument. 139 | */ 140 | fun notNull(): T? { 141 | return ArgumentMatchers.notNull() 142 | } 143 | 144 | /** 145 | * Object argument that is reflection-equal to the given value with support for excluding 146 | * selected fields from a class. 147 | */ 148 | inline fun refEq(value: T, vararg excludeFields: String): T { 149 | return ArgumentMatchers.refEq(value, *excludeFields) ?: createInstance() 150 | } 151 | -------------------------------------------------------------------------------- /mockito-kotlin/src/main/kotlin/org/mockito/kotlin/AdditionalMatchers.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2024 Mockito contributors 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package org.mockito.kotlin 26 | 27 | import org.mockito.AdditionalMatchers 28 | import org.mockito.kotlin.internal.createInstance 29 | import kotlin.reflect.KClass 30 | 31 | /** comparable argument greater than or equal the given value. */ 32 | inline fun > geq(value: T): T { 33 | return AdditionalMatchers.geq(value) ?: createInstance() 34 | } 35 | 36 | /** comparable argument greater than or equal to the given value. */ 37 | inline fun > leq(value: T): T { 38 | return AdditionalMatchers.leq(value) ?: createInstance() 39 | } 40 | 41 | /** comparable argument greater than the given value. */ 42 | inline fun > gt(value: T): T { 43 | return AdditionalMatchers.gt(value) ?: createInstance() 44 | } 45 | 46 | /** comparable argument less than the given value. */ 47 | inline fun > lt(value: T): T { 48 | return AdditionalMatchers.lt(value) ?: createInstance() 49 | } 50 | 51 | /** comparable argument equals to the given value according to their compareTo method. */ 52 | inline fun > cmpEq(value: T): T { 53 | return AdditionalMatchers.cmpEq(value) ?: createInstance() 54 | } 55 | 56 | /** 57 | * Any array argument that is equal to the given array, i.e. it has to have the same type, length, 58 | * and each element has to be equal. 59 | */ 60 | inline fun aryEq(value: Array): Array { 61 | return AdditionalMatchers.aryEq(value) ?: createInstance() 62 | } 63 | 64 | /** 65 | * short array argument that is equal to the given array, i.e. it has to have the same length, and 66 | * each element has to be equal. 67 | */ 68 | fun aryEq(value: ShortArray): ShortArray { 69 | return AdditionalMatchers.aryEq(value) ?: createInstance() 70 | } 71 | 72 | /** 73 | * long array argument that is equal to the given array, i.e. it has to have the same length, and 74 | * each element has to be equal. 75 | */ 76 | fun aryEq(value: LongArray): LongArray { 77 | return AdditionalMatchers.aryEq(value) ?: createInstance() 78 | } 79 | 80 | /** 81 | * int array argument that is equal to the given array, i.e. it has to have the same length, and 82 | * each element has to be equal. 83 | */ 84 | fun aryEq(value: IntArray): IntArray { 85 | return AdditionalMatchers.aryEq(value) ?: createInstance() 86 | } 87 | 88 | /** 89 | * float array argument that is equal to the given array, i.e. it has to have the same length, and 90 | * each element has to be equal. 91 | */ 92 | fun aryEq(value: FloatArray): FloatArray { 93 | return AdditionalMatchers.aryEq(value) ?: createInstance() 94 | } 95 | 96 | /** 97 | * double array argument that is equal to the given array, i.e. it has to have the same length, and 98 | * each element has to be equal. 99 | */ 100 | fun aryEq(value: DoubleArray): DoubleArray { 101 | return AdditionalMatchers.aryEq(value) ?: createInstance() 102 | } 103 | 104 | /** 105 | * char array argument that is equal to the given array, i.e. it has to have the same length, and 106 | * each element has to be equal. 107 | */ 108 | fun aryEq(value: CharArray): CharArray { 109 | return AdditionalMatchers.aryEq(value) ?: createInstance() 110 | } 111 | 112 | /** 113 | * byte array argument that is equal to the given array, i.e. it has to have the same length, and 114 | * each element has to be equal. 115 | */ 116 | fun aryEq(value: ByteArray): ByteArray { 117 | return AdditionalMatchers.aryEq(value) ?: createInstance() 118 | } 119 | 120 | /** 121 | * boolean array argument that is equal to the given array, i.e. it has to have the same length, and 122 | * each element has to be equal. 123 | */ 124 | fun aryEq(value: BooleanArray): BooleanArray { 125 | return AdditionalMatchers.aryEq(value) ?: createInstance() 126 | } 127 | 128 | /** String argument that contains a substring that matches the given regular expression. */ 129 | fun find(regex: Regex): String { 130 | return AdditionalMatchers.find(regex.pattern) ?: "" 131 | } 132 | 133 | /** argument that matches both given argument matchers. */ 134 | inline fun and(left: T, right: T): T { 135 | return AdditionalMatchers.and(left, right) ?: createInstance() 136 | } 137 | 138 | /** argument that matches both given argument matchers. */ 139 | inline fun or(left: T, right: T): T { 140 | return AdditionalMatchers.or(left, right) ?: createInstance() 141 | } 142 | 143 | /** argument that does not match the given argument matcher. */ 144 | inline fun not(matcher: T): T { 145 | return AdditionalMatchers.not(matcher) ?: createInstance() 146 | } 147 | 148 | /** 149 | * float argument that has an absolute difference to the given value that is 150 | * less than the given delta details. 151 | */ 152 | fun eq(value: Double, delta: Double): Double { 153 | return AdditionalMatchers.eq(value, delta) ?: 0.0 154 | } 155 | 156 | /** 157 | * double argument that has an absolute difference to the given value that 158 | * is less than the given delta details. 159 | */ 160 | fun eq(value: Float, delta: Float): Float { 161 | return AdditionalMatchers.eq(value, delta) ?: 0.0f 162 | } 163 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | 86 | # Determine the Java command to use to start the JVM. 87 | if [ -n "$JAVA_HOME" ] ; then 88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 89 | # IBM's JDK on AIX uses strange locations for the executables 90 | JAVACMD="$JAVA_HOME/jre/sh/java" 91 | else 92 | JAVACMD="$JAVA_HOME/bin/java" 93 | fi 94 | if [ ! -x "$JAVACMD" ] ; then 95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 96 | 97 | Please set the JAVA_HOME variable in your environment to match the 98 | location of your Java installation." 99 | fi 100 | else 101 | JAVACMD="java" 102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 103 | 104 | Please set the JAVA_HOME variable in your environment to match the 105 | location of your Java installation." 106 | fi 107 | 108 | # Increase the maximum file descriptors if we can. 109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 110 | MAX_FD_LIMIT=`ulimit -H -n` 111 | if [ $? -eq 0 ] ; then 112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 113 | MAX_FD="$MAX_FD_LIMIT" 114 | fi 115 | ulimit -n $MAX_FD 116 | if [ $? -ne 0 ] ; then 117 | warn "Could not set maximum file descriptor limit: $MAX_FD" 118 | fi 119 | else 120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 121 | fi 122 | fi 123 | 124 | # For Darwin, add options to specify how the application appears in the dock 125 | if $darwin; then 126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 127 | fi 128 | 129 | # For Cygwin or MSYS, switch paths to Windows format before running java 130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 133 | 134 | JAVACMD=`cygpath --unix "$JAVACMD"` 135 | 136 | # We build the pattern for arguments to be converted via cygpath 137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 138 | SEP="" 139 | for dir in $ROOTDIRSRAW ; do 140 | ROOTDIRS="$ROOTDIRS$SEP$dir" 141 | SEP="|" 142 | done 143 | OURCYGPATTERN="(^($ROOTDIRS))" 144 | # Add a user-defined pattern to the cygpath arguments 145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 147 | fi 148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 149 | i=0 150 | for arg in "$@" ; do 151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 153 | 154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 156 | else 157 | eval `echo args$i`="\"$arg\"" 158 | fi 159 | i=`expr $i + 1` 160 | done 161 | case $i in 162 | 0) set -- ;; 163 | 1) set -- "$args0" ;; 164 | 2) set -- "$args0" "$args1" ;; 165 | 3) set -- "$args0" "$args1" "$args2" ;; 166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 172 | esac 173 | fi 174 | 175 | # Escape application args 176 | save () { 177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 178 | echo " " 179 | } 180 | APP_ARGS=`save "$@"` 181 | 182 | # Collect all arguments for the java command, following the shell quoting and substitution rules 183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 184 | 185 | exec "$JAVACMD" "$@" 186 | -------------------------------------------------------------------------------- /mockito-kotlin/src/main/kotlin/org/mockito/kotlin/ArgumentCaptor.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018 Niek Haarman 5 | * Copyright (c) 2007 Mockito contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | package org.mockito.kotlin 27 | 28 | import org.mockito.kotlin.internal.createInstance 29 | import org.mockito.ArgumentCaptor 30 | import java.lang.reflect.Array 31 | import kotlin.reflect.KClass 32 | 33 | /** 34 | * Creates a [KArgumentCaptor] for given type. 35 | */ 36 | inline fun argumentCaptor(): KArgumentCaptor { 37 | return KArgumentCaptor(ArgumentCaptor.forClass(T::class.java), T::class) 38 | } 39 | 40 | /** 41 | * Creates 2 [KArgumentCaptor]s for given types. 42 | */ 43 | inline fun argumentCaptor( 44 | a: KClass = A::class, 45 | b: KClass = B::class 46 | ): Pair, KArgumentCaptor> { 47 | return Pair( 48 | KArgumentCaptor(ArgumentCaptor.forClass(a.java), a), 49 | KArgumentCaptor(ArgumentCaptor.forClass(b.java), b) 50 | ) 51 | } 52 | 53 | /** 54 | * Creates 3 [KArgumentCaptor]s for given types. 55 | */ 56 | inline fun argumentCaptor( 57 | a: KClass = A::class, 58 | b: KClass = B::class, 59 | c: KClass = C::class 60 | ): Triple, KArgumentCaptor, KArgumentCaptor> { 61 | return Triple( 62 | KArgumentCaptor(ArgumentCaptor.forClass(a.java), a), 63 | KArgumentCaptor(ArgumentCaptor.forClass(b.java), b), 64 | KArgumentCaptor(ArgumentCaptor.forClass(c.java), c) 65 | ) 66 | } 67 | 68 | class ArgumentCaptorHolder4( 69 | val first: A, 70 | val second: B, 71 | val third: C, 72 | val fourth: D 73 | ) { 74 | 75 | operator fun component1() = first 76 | operator fun component2() = second 77 | operator fun component3() = third 78 | operator fun component4() = fourth 79 | } 80 | 81 | class ArgumentCaptorHolder5( 82 | val first: A, 83 | val second: B, 84 | val third: C, 85 | val fourth: D, 86 | val fifth: E 87 | ) { 88 | 89 | operator fun component1() = first 90 | operator fun component2() = second 91 | operator fun component3() = third 92 | operator fun component4() = fourth 93 | operator fun component5() = fifth 94 | } 95 | 96 | /** 97 | * Creates 4 [KArgumentCaptor]s for given types. 98 | */ 99 | inline fun argumentCaptor( 100 | a: KClass = A::class, 101 | b: KClass = B::class, 102 | c: KClass = C::class, 103 | d: KClass = D::class 104 | ): ArgumentCaptorHolder4, KArgumentCaptor, KArgumentCaptor, KArgumentCaptor> { 105 | return ArgumentCaptorHolder4( 106 | KArgumentCaptor(ArgumentCaptor.forClass(a.java), a), 107 | KArgumentCaptor(ArgumentCaptor.forClass(b.java), b), 108 | KArgumentCaptor(ArgumentCaptor.forClass(c.java), c), 109 | KArgumentCaptor(ArgumentCaptor.forClass(d.java), d) 110 | ) 111 | } 112 | 113 | /** 114 | * Creates 4 [KArgumentCaptor]s for given types. 115 | */ 116 | inline fun argumentCaptor( 117 | a: KClass = A::class, 118 | b: KClass = B::class, 119 | c: KClass = C::class, 120 | d: KClass = D::class, 121 | e: KClass = E::class 122 | ): ArgumentCaptorHolder5, KArgumentCaptor, KArgumentCaptor, KArgumentCaptor, KArgumentCaptor> { 123 | return ArgumentCaptorHolder5( 124 | KArgumentCaptor(ArgumentCaptor.forClass(a.java), a), 125 | KArgumentCaptor(ArgumentCaptor.forClass(b.java), b), 126 | KArgumentCaptor(ArgumentCaptor.forClass(c.java), c), 127 | KArgumentCaptor(ArgumentCaptor.forClass(d.java), d), 128 | KArgumentCaptor(ArgumentCaptor.forClass(e.java), e) 129 | ) 130 | } 131 | 132 | /** 133 | * Creates a [KArgumentCaptor] for given type, taking in a lambda to allow fast verification. 134 | */ 135 | inline fun argumentCaptor(f: KArgumentCaptor.() -> Unit): KArgumentCaptor { 136 | return argumentCaptor().apply(f) 137 | } 138 | 139 | /** 140 | * Creates a [KArgumentCaptor] for given nullable type. 141 | */ 142 | inline fun nullableArgumentCaptor(): KArgumentCaptor { 143 | return KArgumentCaptor(ArgumentCaptor.forClass(T::class.java), T::class) 144 | } 145 | 146 | /** 147 | * Creates a [KArgumentCaptor] for given nullable type, taking in a lambda to allow fast verification. 148 | */ 149 | inline fun nullableArgumentCaptor(f: KArgumentCaptor.() -> Unit): KArgumentCaptor { 150 | return nullableArgumentCaptor().apply(f) 151 | } 152 | 153 | /** 154 | * Alias for [ArgumentCaptor.capture]. 155 | */ 156 | inline fun capture(captor: ArgumentCaptor): T { 157 | return captor.capture() ?: createInstance() 158 | } 159 | 160 | class KArgumentCaptor( 161 | private val captor: ArgumentCaptor, 162 | private val tClass: KClass<*> 163 | ) { 164 | 165 | /** 166 | * The first captured value of the argument. 167 | * @throws IndexOutOfBoundsException if the value is not available. 168 | */ 169 | val firstValue: T 170 | get() = captor.firstValue 171 | 172 | /** 173 | * The second captured value of the argument. 174 | * @throws IndexOutOfBoundsException if the value is not available. 175 | */ 176 | val secondValue: T 177 | get() = captor.secondValue 178 | 179 | /** 180 | * The third captured value of the argument. 181 | * @throws IndexOutOfBoundsException if the value is not available. 182 | */ 183 | val thirdValue: T 184 | get() = captor.thirdValue 185 | 186 | /** 187 | * The last captured value of the argument. 188 | * @throws IndexOutOfBoundsException if the value is not available. 189 | */ 190 | val lastValue: T 191 | get() = captor.lastValue 192 | 193 | val allValues: List 194 | get() = captor.allValues 195 | 196 | @Suppress("UNCHECKED_CAST") 197 | fun capture(): T { 198 | // Special handling for arrays to make it work for varargs 199 | // In Kotlin we want have to capture vararg like this `verify(m).methodName(*captor.capture())` to make the types work 200 | // If we return null for array types, the spread `*` operator will fail with NPE 201 | // If we return empty array, it will fail in MatchersBinder.validateMatchers 202 | // In Java, `captor.capture` returns null and so the method is called with `[null]` 203 | // In Kotlin, we have to create `[null]` explicitly. 204 | // This code-path is applied for non-vararg array arguments as well, but it seems to work fine. 205 | return captor.capture() ?: if (tClass.java.isArray) { 206 | singleElementArray() 207 | } else { 208 | createInstance(tClass) 209 | } as T 210 | } 211 | 212 | private fun singleElementArray(): Any? = Array.newInstance(tClass.java.componentType, 1) 213 | } 214 | 215 | val ArgumentCaptor.firstValue: T 216 | get() = allValues[0] 217 | 218 | val ArgumentCaptor.secondValue: T 219 | get() = allValues[1] 220 | 221 | val ArgumentCaptor.thirdValue: T 222 | get() = allValues[2] 223 | 224 | val ArgumentCaptor.lastValue: T 225 | get() = allValues.last() 226 | -------------------------------------------------------------------------------- /tests/src/test/kotlin/test/ArgumentCaptorTest.kt: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import com.nhaarman.expect.expect 4 | import com.nhaarman.expect.expectErrorWithMessage 5 | import org.junit.Test 6 | import org.mockito.kotlin.* 7 | import java.util.* 8 | 9 | class ArgumentCaptorTest : TestBase() { 10 | 11 | @Test 12 | fun argumentCaptor_withSingleValue() { 13 | /* Given */ 14 | val date: Date = mock() 15 | 16 | /* When */ 17 | date.time = 5L 18 | 19 | /* Then */ 20 | val captor = argumentCaptor() 21 | verify(date).time = captor.capture() 22 | expect(captor.lastValue).toBe(5L) 23 | } 24 | 25 | @Test 26 | fun argumentCaptor_destructuring2() { 27 | /* Given */ 28 | val date: Date = mock() 29 | 30 | /* When */ 31 | date.time = 5L 32 | 33 | /* Then */ 34 | val (captor1, captor2) = argumentCaptor() 35 | verify(date).time = captor1.capture() 36 | verify(date).time = captor2.capture() 37 | expect(captor1.lastValue).toBe(5L) 38 | expect(captor2.lastValue).toBe(5L) 39 | } 40 | 41 | @Test 42 | fun argumentCaptor_destructuring3() { 43 | /* Given */ 44 | val date: Date = mock() 45 | 46 | /* When */ 47 | date.time = 5L 48 | 49 | /* Then */ 50 | val (captor1, captor2, captor3) = argumentCaptor() 51 | val verifyCaptor: KArgumentCaptor.() -> Unit = { 52 | verify(date).time = capture() 53 | expect(lastValue).toBe(5L) 54 | } 55 | captor1.apply(verifyCaptor) 56 | captor2.apply(verifyCaptor) 57 | captor3.apply(verifyCaptor) 58 | } 59 | 60 | @Test 61 | fun argumentCaptor_destructuring4() { 62 | /* Given */ 63 | val date: Date = mock() 64 | 65 | /* When */ 66 | date.time = 5L 67 | 68 | /* Then */ 69 | val (captor1, captor2, captor3, captor4) = argumentCaptor() 70 | val verifyCaptor: KArgumentCaptor.() -> Unit = { 71 | verify(date).time = capture() 72 | expect(lastValue).toBe(5L) 73 | } 74 | captor1.apply(verifyCaptor) 75 | captor2.apply(verifyCaptor) 76 | captor3.apply(verifyCaptor) 77 | captor4.apply(verifyCaptor) 78 | } 79 | 80 | @Test 81 | fun argumentCaptor_destructuring5() { 82 | /* Given */ 83 | val date: Date = mock() 84 | 85 | /* When */ 86 | date.time = 5L 87 | 88 | /* Then */ 89 | val (captor1, captor2, captor3, captor4, captor5) = argumentCaptor() 90 | val verifyCaptor: KArgumentCaptor.() -> Unit = { 91 | verify(date).time = capture() 92 | expect(lastValue).toBe(5L) 93 | } 94 | captor1.apply(verifyCaptor) 95 | captor2.apply(verifyCaptor) 96 | captor3.apply(verifyCaptor) 97 | captor4.apply(verifyCaptor) 98 | captor5.apply(verifyCaptor) 99 | } 100 | 101 | @Test 102 | fun argumentCaptor_withNullValue_usingNonNullable() { 103 | /* Given */ 104 | val m: Methods = mock() 105 | 106 | /* When */ 107 | m.nullableString(null) 108 | 109 | /* Then */ 110 | val captor = argumentCaptor() 111 | verify(m).nullableString(captor.capture()) 112 | expect(captor.lastValue).toBeNull() 113 | } 114 | 115 | @Test 116 | fun argumentCaptor_withNullValue_usingNullable() { 117 | /* Given */ 118 | val m: Methods = mock() 119 | 120 | /* When */ 121 | m.nullableString(null) 122 | 123 | /* Then */ 124 | val captor = nullableArgumentCaptor() 125 | verify(m).nullableString(captor.capture()) 126 | expect(captor.lastValue).toBeNull() 127 | } 128 | 129 | @Test 130 | fun argumentCaptor_multipleValues() { 131 | /* Given */ 132 | val date: Date = mock() 133 | 134 | /* When */ 135 | date.time = 5L 136 | date.time = 7L 137 | 138 | /* Then */ 139 | val captor = argumentCaptor() 140 | verify(date, times(2)).time = captor.capture() 141 | expect(captor.allValues).toBe(listOf(5, 7)) 142 | } 143 | 144 | @Test 145 | fun argumentCaptor_multipleValuesIncludingNull() { 146 | /* Given */ 147 | val m: Methods = mock() 148 | 149 | /* When */ 150 | m.nullableString("test") 151 | m.nullableString(null) 152 | 153 | /* Then */ 154 | val captor = nullableArgumentCaptor() 155 | verify(m, times(2)).nullableString(captor.capture()) 156 | expect(captor.allValues).toBe(listOf("test", null)) 157 | } 158 | 159 | @Test 160 | fun argumentCaptor_callProperties() { 161 | /* Given */ 162 | val m: Methods = mock() 163 | 164 | /* When */ 165 | m.int(1) 166 | m.int(2) 167 | m.int(3) 168 | m.int(4) 169 | m.int(5) 170 | 171 | /* Then */ 172 | argumentCaptor().apply { 173 | verify(m, times(5)).int(capture()) 174 | 175 | expect(firstValue).toBe(1) 176 | expect(secondValue).toBe(2) 177 | expect(thirdValue).toBe(3) 178 | expect(lastValue).toBe(5) 179 | } 180 | } 181 | 182 | @Test(expected = IndexOutOfBoundsException::class) 183 | fun argumentCaptor_callPropertyNotAvailable() { 184 | /* Given */ 185 | val m: Methods = mock() 186 | 187 | /* When */ 188 | m.int(1) 189 | 190 | /* Then */ 191 | argumentCaptor().apply { 192 | verify(m).int(capture()) 193 | 194 | expect(secondValue).toBe(2) 195 | } 196 | } 197 | 198 | @Test 199 | fun argumentCaptor_withSingleValue_lambda() { 200 | /* Given */ 201 | val date: Date = mock() 202 | 203 | /* When */ 204 | date.time = 5L 205 | 206 | /* Then */ 207 | argumentCaptor { 208 | verify(date).time = capture() 209 | expect(lastValue).toBe(5L) 210 | } 211 | } 212 | 213 | @Test 214 | fun argumentCaptor_withSingleValue_lambda_properlyFails() { 215 | /* Given */ 216 | val date: Date = mock() 217 | 218 | /* When */ 219 | date.time = 5L 220 | 221 | /* Then */ 222 | expectErrorWithMessage("Expected: 3 but was: 5") on { 223 | argumentCaptor { 224 | verify(date).time = capture() 225 | expect(lastValue).toBe(3L) 226 | } 227 | } 228 | } 229 | 230 | @Test 231 | fun argumentCaptor_vararg() { 232 | /* Given */ 233 | val m: Methods = mock() 234 | 235 | /* When */ 236 | m.varargBooleanResult("a", "b", "c") 237 | 238 | /* Then */ 239 | val captor = argumentCaptor>() 240 | verify(m).varargBooleanResult(*captor.capture()) 241 | expect(captor.firstValue.toList()).toBe(listOf("a", "b", "c")) 242 | } 243 | 244 | @Test 245 | fun argumentCaptor_empty_vararg() { 246 | /* Given */ 247 | val m: Methods = mock() 248 | 249 | /* When */ 250 | m.varargBooleanResult() 251 | 252 | /* Then */ 253 | val captor = argumentCaptor>() 254 | verify(m).varargBooleanResult(*captor.capture()) 255 | expect(captor.firstValue.toList()).toBe(listOf()) 256 | } 257 | 258 | @Test 259 | fun argumentCaptor_arg_vararg() { 260 | /* Given */ 261 | val m: Methods = mock() 262 | 263 | /* When */ 264 | m.argAndVararg("first", "a", "b", "c") 265 | 266 | /* Then */ 267 | val captor = argumentCaptor>() 268 | verify(m).argAndVararg(any(), *captor.capture()) 269 | expect(captor.firstValue.toList()).toBe(listOf("a", "b", "c")) 270 | } 271 | 272 | @Test 273 | fun argumentCaptor_intarray() { 274 | /* Given */ 275 | val m: Methods = mock() 276 | 277 | /* When */ 278 | m.intArray(intArrayOf(1, 2, 3)) 279 | 280 | /* Then */ 281 | val captor = argumentCaptor() 282 | verify(m).intArray(captor.capture()) 283 | expect(captor.firstValue.toList()).toBe(listOf(1, 2, 3)) 284 | } 285 | 286 | @Test 287 | fun argumentCaptor_array() { 288 | /* Given */ 289 | val m: Methods = mock() 290 | 291 | /* When */ 292 | m.stringArray(arrayOf("a", "b", "c")) 293 | 294 | /* Then */ 295 | val captor = argumentCaptor>() 296 | verify(m).stringArray(captor.capture()) 297 | expect(captor.firstValue.toList()).toBe(listOf("a", "b", "c")) 298 | } 299 | 300 | @Test 301 | fun argumentCaptor_empty_array() { 302 | /* Given */ 303 | val m: Methods = mock() 304 | 305 | /* When */ 306 | m.stringArray(arrayOf()) 307 | 308 | /* Then */ 309 | val captor = argumentCaptor>() 310 | verify(m).stringArray(captor.capture()) 311 | expect(captor.firstValue.toList()).toBe(listOf()) 312 | } 313 | } 314 | -------------------------------------------------------------------------------- /mockito-kotlin/src/main/kotlin/org/mockito/kotlin/Verification.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018 Niek Haarman 5 | * Copyright (c) 2007 Mockito contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | package org.mockito.kotlin 27 | 28 | import org.mockito.kotlin.internal.createInstance 29 | import kotlinx.coroutines.runBlocking 30 | import org.mockito.Mockito 31 | import org.mockito.kotlin.internal.KInOrderDecorator 32 | import org.mockito.verification.VerificationAfterDelay 33 | import org.mockito.verification.VerificationMode 34 | import org.mockito.verification.VerificationWithTimeout 35 | 36 | /** 37 | * Verifies certain behavior happened once. 38 | * 39 | * Alias for [Mockito.verify]. 40 | */ 41 | fun verify(mock: T): T { 42 | return Mockito.verify(mock)!! 43 | } 44 | 45 | /** 46 | * Verifies certain suspending behavior happened once. 47 | * 48 | * Warning: Only one method call can be verified in the function. 49 | * Subsequent method calls are ignored! 50 | */ 51 | fun verifyBlocking(mock: T, f: suspend T.() -> Unit) { 52 | val m = Mockito.verify(mock) 53 | runBlocking { m.f() } 54 | } 55 | 56 | /** 57 | * Verifies certain behavior happened at least once / exact number of times / never. 58 | * 59 | * Warning: Only one method call can be verified in the function. 60 | * Subsequent method calls are ignored! 61 | */ 62 | fun verifyBlocking(mock: T, mode: VerificationMode, f: suspend T.() -> Unit) { 63 | val m = Mockito.verify(mock, mode) 64 | runBlocking { m.f() } 65 | } 66 | 67 | /** 68 | * Verifies certain behavior happened at least once / exact number of times / never. 69 | * 70 | * Alias for [Mockito.verify]. 71 | */ 72 | fun verify(mock: T, mode: VerificationMode): T { 73 | return Mockito.verify(mock, mode)!! 74 | } 75 | 76 | /** 77 | * Verifies that no interactions happened on given mocks beyond the previously verified interactions. 78 | * 79 | * Alias for [Mockito.verifyNoMoreInteractions]. 80 | */ 81 | fun verifyNoMoreInteractions(vararg mocks: T) { 82 | Mockito.verifyNoMoreInteractions(*mocks) 83 | } 84 | 85 | /** 86 | * Checks if any of given mocks has any unverified interaction. 87 | * 88 | * Alias for [Mockito.verifyNoInteractions]. 89 | */ 90 | fun verifyNoInteractions(vararg mocks: Any) { 91 | Mockito.verifyNoInteractions(*mocks) 92 | } 93 | 94 | /** 95 | * Allows verifying exact number of invocations. 96 | * 97 | * Alias for [Mockito.times]. 98 | */ 99 | fun times(numInvocations: Int): VerificationMode { 100 | return Mockito.times(numInvocations)!! 101 | } 102 | 103 | /** 104 | * Allows at-least-x verification. 105 | * 106 | * Alias for [Mockito.atLeast]. 107 | */ 108 | fun atLeast(numInvocations: Int): VerificationMode { 109 | return Mockito.atLeast(numInvocations)!! 110 | } 111 | 112 | /** 113 | * Allows at-least-once verification. 114 | * 115 | * Alias for [Mockito.atLeastOnce]. 116 | */ 117 | fun atLeastOnce(): VerificationMode { 118 | return Mockito.atLeastOnce()!! 119 | } 120 | 121 | /** 122 | * Allows at-most-x verification. 123 | * 124 | * Alias for [Mockito.atMost]. 125 | */ 126 | fun atMost(maxNumberOfInvocations: Int): VerificationMode { 127 | return Mockito.atMost(maxNumberOfInvocations)!! 128 | } 129 | 130 | /** 131 | * Allows non-greedy verification in order. 132 | * 133 | * Alias for [Mockito.calls]. 134 | */ 135 | fun calls(wantedNumberOfInvocations: Int): VerificationMode { 136 | return Mockito.calls(wantedNumberOfInvocations)!! 137 | } 138 | 139 | /** 140 | * Alias for [times] with parameter `0`. 141 | */ 142 | fun never(): VerificationMode { 143 | return Mockito.never()!! 144 | } 145 | 146 | /** 147 | * Use this method in order to only clear invocations, when stubbing is non-trivial. 148 | * 149 | * Alias for [Mockito.clearInvocations]. 150 | */ 151 | fun clearInvocations(vararg mocks: T) { 152 | Mockito.clearInvocations(*mocks) 153 | } 154 | 155 | /** 156 | * Adds a description to be printed if verification fails. 157 | * 158 | * Alias for [Mockito.description]. 159 | */ 160 | fun description(description: String): VerificationMode { 161 | return Mockito.description(description) 162 | } 163 | 164 | /** 165 | * Allows verifying over a given period. It causes a verify to wait for a specified period of time for a desired 166 | * interaction rather than failing immediately if has not already happened. May be useful for testing in concurrent 167 | * conditions. 168 | */ 169 | fun after(millis: Long): VerificationAfterDelay { 170 | return Mockito.after(millis)!! 171 | } 172 | 173 | /** 174 | * Allows verifying with timeout. It causes a verify to wait for a specified period of time for a desired 175 | * interaction rather than fails immediately if has not already happened. May be useful for testing in concurrent 176 | * conditions. 177 | */ 178 | fun timeout(millis: Long): VerificationWithTimeout { 179 | return Mockito.timeout(millis)!! 180 | } 181 | 182 | /** 183 | * Ignores stubbed methods of given mocks for the sake of verification. 184 | * 185 | * Alias for [Mockito.ignoreStubs]. 186 | */ 187 | fun ignoreStubs(vararg mocks: Any): Array { 188 | return Mockito.ignoreStubs(*mocks)!! 189 | } 190 | 191 | /** 192 | * Creates [KInOrder] object that allows verifying mocks in order. 193 | * 194 | * Wrapper for [Mockito.inOrder] that also allows to verify suspending method calls. 195 | */ 196 | fun inOrder(vararg mocks: Any): KInOrder { 197 | return KInOrderDecorator(Mockito.inOrder(*mocks)!!) 198 | } 199 | 200 | /** 201 | * Creates [KInOrder] object that allows verifying mocks in order. 202 | * Accepts a lambda to allow easy evaluation. 203 | * 204 | * Wrapper for [Mockito.inOrder] that also allows to verify suspending method calls. 205 | */ 206 | inline fun inOrder( 207 | vararg mocks: Any, 208 | evaluation: KInOrder.() -> Unit 209 | ) { 210 | KInOrderDecorator(Mockito.inOrder(*mocks)).evaluation() 211 | } 212 | 213 | /** 214 | * Allows [KInOrder] verification for a single mocked instance: 215 | * 216 | * mock.inOrder { 217 | * verify().foo() 218 | * verifyBlocking { bar() } 219 | * } 220 | * 221 | */ 222 | inline fun T.inOrder(block: InOrderOnType.() -> Any) { 223 | block.invoke(InOrderOnType(this)) 224 | } 225 | 226 | class InOrderOnType(private val t: T) : KInOrder by inOrder(t as Any) { 227 | 228 | /** 229 | * Verifies certain behavior happened once in order. 230 | */ 231 | fun verify(): T = verify(t) 232 | 233 | /** 234 | * Verifies certain behavior happened at least once / exact number of times / never in order. 235 | */ 236 | fun verify(mode: VerificationMode): T = verify(t, mode) 237 | 238 | /** 239 | * Verifies certain suspending behavior happened once in order. 240 | * 241 | * Warning: Only one method call can be verified in the function. 242 | * Subsequent method calls are ignored! 243 | */ 244 | fun verifyBlocking(f: suspend T.() -> Unit) = verifyBlocking(t, f) 245 | 246 | /** 247 | * Verifies certain suspending behavior happened at least once / exact number of times / never in order. 248 | * 249 | * Warning: Only one method call can be verified in the function. 250 | * Subsequent method calls are ignored! 251 | */ 252 | fun verifyBlocking(mode: VerificationMode, f: suspend T.() -> Unit) = verifyBlocking(t, mode, f) 253 | } 254 | 255 | /** 256 | * Allows checking if given method was the only one invoked. 257 | */ 258 | fun only(): VerificationMode { 259 | return Mockito.only()!! 260 | } 261 | 262 | /** 263 | * For usage with verification only. 264 | * 265 | * For example: 266 | * verify(myObject).doSomething(check { assertThat(it, is("Test")) }) 267 | * 268 | * @param predicate A function that performs actions to verify an argument [T]. 269 | */ 270 | inline fun check(noinline predicate: (T) -> Unit): T { 271 | return Mockito.argThat { arg: T? -> 272 | if (arg == null) error( 273 | """ 274 | The argument passed to the predicate was null. 275 | 276 | If you are trying to verify an argument to be null, use `isNull()`. 277 | If you are using `check` as part of a stubbing, use `argThat` or `argForWhich` instead. 278 | """.trimIndent() 279 | ) 280 | 281 | try { 282 | predicate(arg) 283 | true 284 | } catch (e: Error) { 285 | e.printStackTrace() 286 | false 287 | } 288 | } ?: createInstance(T::class) 289 | } 290 | -------------------------------------------------------------------------------- /tests/src/test/kotlin/test/MatchersTest.kt: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import com.nhaarman.expect.expect 4 | import com.nhaarman.expect.expectErrorWithMessage 5 | import org.junit.Test 6 | import org.mockito.ArgumentMatcher 7 | import org.mockito.invocation.InvocationOnMock 8 | import org.mockito.kotlin.* 9 | import org.mockito.stubbing.Answer 10 | import java.io.IOException 11 | 12 | class MatchersTest : TestBase() { 13 | 14 | @Test 15 | fun anyString() { 16 | mock().apply { 17 | string("") 18 | verify(this).string(any()) 19 | } 20 | } 21 | 22 | @Test 23 | fun anyInt() { 24 | mock().apply { 25 | int(3) 26 | verify(this).int(any()) 27 | } 28 | } 29 | 30 | @Test 31 | fun anyClosedClass() { 32 | mock().apply { 33 | closed(Closed()) 34 | verify(this).closed(any()) 35 | } 36 | } 37 | 38 | @Test 39 | fun anyIntArray() { 40 | mock().apply { 41 | intArray(intArrayOf()) 42 | verify(this).intArray(any()) 43 | } 44 | } 45 | 46 | @Test 47 | fun anyClassArray() { 48 | mock().apply { 49 | closedArray(arrayOf(Closed())) 50 | verify(this).closedArray(anyArray()) 51 | } 52 | } 53 | 54 | @Test 55 | fun anyNullableClassArray() { 56 | mock().apply { 57 | closedNullableArray(arrayOf(Closed(), null)) 58 | verify(this).closedNullableArray(anyArray()) 59 | } 60 | } 61 | 62 | @Test 63 | fun anyStringVararg() { 64 | mock().apply { 65 | closedVararg(Closed(), Closed()) 66 | verify(this).closedVararg(anyVararg()) 67 | } 68 | } 69 | 70 | @Test 71 | fun anyVarargMatching() { 72 | mock().apply { 73 | whenever(varargBooleanResult(anyVararg())).thenReturn(true) 74 | expect(varargBooleanResult()).toBe(true) 75 | } 76 | } 77 | 78 | @Test 79 | fun anyNull_neverVerifiesAny() { 80 | mock().apply { 81 | nullableString(null) 82 | verify(this, never()).nullableString(any()) 83 | } 84 | } 85 | 86 | @Test 87 | fun anyNull_verifiesAnyOrNull() { 88 | mock().apply { 89 | nullableString(null) 90 | verify(this).nullableString(anyOrNull()) 91 | } 92 | } 93 | 94 | @Test 95 | fun anyNull_forPrimitiveBoolean() { 96 | mock().apply { 97 | boolean(false) 98 | verify(this).boolean(anyOrNull()) 99 | } 100 | } 101 | 102 | @Test 103 | fun anyNull_forPrimitiveByte() { 104 | mock().apply { 105 | byte(3) 106 | verify(this).byte(anyOrNull()) 107 | } 108 | } 109 | 110 | @Test 111 | fun anyNull_forPrimitiveChar() { 112 | mock().apply { 113 | char('a') 114 | verify(this).char(anyOrNull()) 115 | } 116 | } 117 | 118 | @Test 119 | fun anyNull_forPrimitiveShort() { 120 | mock().apply { 121 | short(3) 122 | verify(this).short(anyOrNull()) 123 | } 124 | } 125 | 126 | @Test 127 | fun anyNull_forPrimitiveInt() { 128 | mock().apply { 129 | int(3) 130 | verify(this).int(anyOrNull()) 131 | } 132 | } 133 | 134 | @Test 135 | fun anyNull_forPrimitiveLong() { 136 | mock().apply { 137 | long(3) 138 | verify(this).long(anyOrNull()) 139 | } 140 | } 141 | 142 | @Test 143 | fun anyNull_forPrimitiveFloat() { 144 | mock().apply { 145 | float(3f) 146 | verify(this).float(anyOrNull()) 147 | } 148 | } 149 | 150 | @Test 151 | fun anyNull_forPrimitiveDouble() { 152 | mock().apply { 153 | double(3.0) 154 | verify(this).double(anyOrNull()) 155 | } 156 | } 157 | 158 | /** https://github.com/nhaarman/mockito-kotlin/issues/27 */ 159 | @Test 160 | fun anyThrowableWithSingleThrowableConstructor() { 161 | mock().apply { 162 | throwableClass(ThrowableClass(IOException())) 163 | verify(this).throwableClass(any()) 164 | } 165 | } 166 | 167 | @Test 168 | fun listArgThat() { 169 | mock().apply { 170 | closedList(listOf(Closed(), Closed())) 171 | verify(this).closedList( 172 | argThat { 173 | size == 2 174 | } 175 | ) 176 | } 177 | } 178 | 179 | @Test 180 | fun listArgForWhich() { 181 | mock().apply { 182 | closedList(listOf(Closed(), Closed())) 183 | verify(this).closedList( 184 | argForWhich { 185 | size == 2 186 | } 187 | ) 188 | } 189 | } 190 | 191 | @Test 192 | fun listArgWhere() { 193 | mock().apply { 194 | closedList(listOf(Closed(), Closed())) 195 | verify(this).closedList( 196 | argWhere { 197 | it.size == 2 198 | } 199 | ) 200 | } 201 | } 202 | 203 | @Test 204 | fun listArgCheck() { 205 | mock().apply { 206 | closedList(listOf(Closed(), Closed())) 207 | verify(this).closedList( 208 | check { 209 | expect(it.size).toBe(2) 210 | } 211 | ) 212 | } 213 | } 214 | 215 | @Test 216 | fun checkProperlyFails() { 217 | mock().apply { 218 | closedList(listOf(Closed(), Closed())) 219 | 220 | expectErrorWithMessage("Argument(s) are different!") on { 221 | verify(this).closedList( 222 | check { 223 | expect(it.size).toBe(1) 224 | } 225 | ) 226 | } 227 | } 228 | } 229 | 230 | @Test 231 | fun checkWithNullArgument_throwsError() { 232 | mock().apply { 233 | nullableString(null) 234 | 235 | expectErrorWithMessage("null").on { 236 | verify(this).nullableString(check {}) 237 | } 238 | } 239 | } 240 | 241 | @Test 242 | fun isA_withNonNullableString() { 243 | mock().apply { 244 | string("") 245 | verify(this).string(isA()) 246 | } 247 | } 248 | 249 | @Test 250 | fun isA_withNullableString() { 251 | mock().apply { 252 | nullableString("") 253 | verify(this).nullableString(isA()) 254 | } 255 | } 256 | 257 | @Test 258 | fun same_withNonNullArgument() { 259 | mock().apply { 260 | string("") 261 | verify(this).string(same("")) 262 | } 263 | } 264 | 265 | @Test 266 | fun same_withNullableNonNullArgument() { 267 | mock().apply { 268 | nullableString("") 269 | verify(this).nullableString(same("")) 270 | } 271 | } 272 | 273 | @Test 274 | fun same_withNullArgument() { 275 | mock().apply { 276 | nullableString(null) 277 | verify(this).nullableString(same(null)) 278 | } 279 | } 280 | 281 | @Test 282 | fun testVarargAnySuccess() { 283 | /* Given */ 284 | val t = mock() 285 | // a matcher to check if any of the varargs was equals to "b" 286 | val matcher = VarargAnyMatcher({ "b" == it }, String::class.java, true, false) 287 | 288 | /* When */ 289 | whenever(t.varargBooleanResult(argThat(matcher))).thenAnswer(matcher) 290 | 291 | /* Then */ 292 | expect(t.varargBooleanResult("a", "b", "c")).toBe(true) 293 | } 294 | 295 | @Test 296 | fun testVarargAnyFail() { 297 | /* Given */ 298 | val t = mock() 299 | // a matcher to check if any of the varargs was equals to "d" 300 | val matcher = VarargAnyMatcher({ "d" == it }, String::class.java, true, false) 301 | 302 | /* When */ 303 | whenever(t.varargBooleanResult(argThat(matcher))).thenAnswer(matcher) 304 | 305 | /* Then */ 306 | expect(t.varargBooleanResult("a", "b", "c")).toBe(false) 307 | } 308 | 309 | /** https://github.com/nhaarman/mockito-kotlin/issues/328 */ 310 | @Test 311 | fun testRefEqForNonNullableParameter() { 312 | mock().apply { 313 | /* When */ 314 | val array = intArrayOf(2, 3) 315 | intArray(array) 316 | 317 | /* Then */ 318 | verify(this).intArray(refEq(array)) 319 | } 320 | } 321 | 322 | /** 323 | * a VarargMatcher implementation for varargs of type [T] that will answer with type [R] if any of the var args 324 | * matched. Needs to keep state between matching invocations. 325 | */ 326 | private class VarargAnyMatcher( 327 | private val match: ((T) -> Boolean), 328 | private val clazz: Class, 329 | private val success: R, 330 | private val failure: R 331 | ) : ArgumentMatcher, Answer { 332 | private var anyMatched = false 333 | 334 | override fun matches(t: T): Boolean { 335 | @Suppress("UNCHECKED_CAST") // No idea how to solve this better 336 | anyMatched = (t as Array).any(match) 337 | return anyMatched 338 | } 339 | 340 | override fun answer(i: InvocationOnMock) = if (anyMatched) success else failure 341 | 342 | override fun type(): Class<*> = java.lang.reflect.Array.newInstance(clazz, 0).javaClass 343 | } 344 | } 345 | -------------------------------------------------------------------------------- /tests/src/test/kotlin/test/OngoingStubbingTest.kt: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import com.nhaarman.expect.expect 4 | import com.nhaarman.expect.expectErrorWithMessage 5 | import com.nhaarman.expect.fail 6 | import org.junit.Assume.assumeFalse 7 | import org.junit.Test 8 | import org.mockito.Mockito 9 | import org.mockito.exceptions.misusing.UnfinishedStubbingException 10 | import org.mockito.kotlin.any 11 | import org.mockito.kotlin.argThat 12 | import org.mockito.kotlin.check 13 | import org.mockito.kotlin.doAnswer 14 | import org.mockito.kotlin.doReturn 15 | import org.mockito.kotlin.doReturnConsecutively 16 | import org.mockito.kotlin.doThrow 17 | import org.mockito.kotlin.mock 18 | import org.mockito.kotlin.stub 19 | import org.mockito.kotlin.stubbing 20 | import org.mockito.kotlin.whenever 21 | import org.mockito.stubbing.Answer 22 | 23 | class OngoingStubbingTest : TestBase() { 24 | 25 | @Test 26 | fun testOngoingStubbing_methodCall() { 27 | /* Given */ 28 | val mock = mock() 29 | mock { 30 | on(mock.stringResult()).doReturn("A") 31 | } 32 | 33 | /* When */ 34 | val result = mock.stringResult() 35 | 36 | /* Then */ 37 | expect(result).toBe("A") 38 | } 39 | 40 | @Test 41 | fun testOngoingStubbing_builder() { 42 | /* Given */ 43 | val mock = mock { mock -> 44 | on { builderMethod() } doReturn mock 45 | } 46 | 47 | /* When */ 48 | val result = mock.builderMethod() 49 | 50 | /* Then */ 51 | expect(result).toBeTheSameAs(mock) 52 | } 53 | 54 | @Test 55 | fun testOngoingStubbing_nullable() { 56 | /* Given */ 57 | val mock = mock { 58 | on { nullableStringResult() } doReturn "Test" 59 | } 60 | 61 | /* When */ 62 | val result = mock.nullableStringResult() 63 | 64 | /* Then */ 65 | expect(result).toBe("Test") 66 | } 67 | 68 | @Test 69 | fun testOngoingStubbing_doThrow() { 70 | /* Given */ 71 | val mock = mock { 72 | on { builderMethod() } doThrow IllegalArgumentException() 73 | } 74 | 75 | try { 76 | /* When */ 77 | mock.builderMethod() 78 | fail("No exception thrown") 79 | } catch (e: IllegalArgumentException) { 80 | } 81 | } 82 | 83 | @Test 84 | fun testOngoingStubbing_doThrowClass() { 85 | /* Given */ 86 | val mock = mock { 87 | on { builderMethod() } doThrow IllegalArgumentException::class 88 | } 89 | 90 | try { 91 | /* When */ 92 | mock.builderMethod() 93 | fail("No exception thrown") 94 | } catch (e: IllegalArgumentException) { 95 | } 96 | } 97 | 98 | @Test 99 | fun testOngoingStubbing_doThrowVarargs() { 100 | /* Given */ 101 | val mock = mock { 102 | on { builderMethod() }.doThrow( 103 | IllegalArgumentException(), 104 | UnsupportedOperationException() 105 | ) 106 | } 107 | 108 | try { 109 | /* When */ 110 | mock.builderMethod() 111 | fail("No exception thrown") 112 | } catch (e: IllegalArgumentException) { 113 | } 114 | 115 | try { 116 | /* When */ 117 | mock.builderMethod() 118 | fail("No exception thrown") 119 | } catch (e: UnsupportedOperationException) { 120 | } 121 | } 122 | 123 | @Test 124 | fun testOngoingStubbing_doThrowClassVarargs() { 125 | /* Given */ 126 | val mock = mock { 127 | on { builderMethod() }.doThrow( 128 | IllegalArgumentException::class, 129 | UnsupportedOperationException::class 130 | ) 131 | } 132 | 133 | try { 134 | /* When */ 135 | mock.builderMethod() 136 | fail("No exception thrown") 137 | } catch (e: IllegalArgumentException) { 138 | } 139 | 140 | try { 141 | /* When */ 142 | mock.builderMethod() 143 | fail("No exception thrown") 144 | } catch (e: UnsupportedOperationException) { 145 | } 146 | } 147 | 148 | @Test 149 | fun testOngoingStubbing_doAnswer_lambda() { 150 | /* Given */ 151 | val mock = mock { 152 | on { stringResult() } doAnswer { "result" } 153 | } 154 | 155 | /* When */ 156 | val result = mock.stringResult() 157 | 158 | /* Then */ 159 | expect(result).toBe("result") 160 | } 161 | 162 | @Test 163 | fun testOngoingStubbing_doAnswer_instance() { 164 | /* Given */ 165 | val mock = mock { 166 | on { stringResult() } doAnswer Answer { "result" } 167 | } 168 | 169 | /* When */ 170 | val result = mock.stringResult() 171 | 172 | /* Then */ 173 | expect(result).toBe("result") 174 | } 175 | 176 | @Test 177 | fun testOngoingStubbing_doAnswer_returnsSelf() { 178 | /* Given */ 179 | val mock = mock { 180 | on { builderMethod() } doAnswer Mockito.RETURNS_SELF 181 | } 182 | 183 | /* When */ 184 | val result = mock.builderMethod() 185 | 186 | /* Then */ 187 | expect(result).toBe(mock) 188 | } 189 | 190 | @Test 191 | fun testOngoingStubbing_doAnswer_withArgument() { 192 | /* Given */ 193 | val mock = mock { 194 | on { stringResult(any()) } doAnswer { "${it.arguments[0]}-result" } 195 | } 196 | 197 | /* When */ 198 | val result = mock.stringResult("argument") 199 | 200 | /* Then */ 201 | expect(result).toBe("argument-result") 202 | } 203 | 204 | @Test 205 | fun testMockStubbingAfterCreatingMock() { 206 | val mock = mock() 207 | 208 | //create stub after creation of mock 209 | mock.stub { 210 | on { stringResult() } doReturn "result" 211 | } 212 | 213 | /* When */ 214 | val result = mock.stringResult() 215 | 216 | /* Then */ 217 | expect(result).toBe("result") 218 | } 219 | 220 | @Test 221 | fun testOverrideDefaultStub() { 222 | /* Given mock with stub */ 223 | val mock = mock { 224 | on { stringResult() } doReturn "result1" 225 | } 226 | 227 | /* override stub */ 228 | mock.stub { 229 | on { stringResult() } doReturn "result2" 230 | } 231 | 232 | /* When */ 233 | val result = mock.stringResult() 234 | 235 | /* Then */ 236 | expect(result).toBe("result2") 237 | } 238 | 239 | @Test 240 | fun stubbingTwiceWithArgumentMatchers() { 241 | /* When */ 242 | val mock = mock { 243 | on { stringResult(argThat { this == "A" }) } doReturn "A" 244 | on { stringResult(argThat { this == "B" }) } doReturn "B" 245 | } 246 | 247 | /* Then */ 248 | expect(mock.stringResult("A")).toBe("A") 249 | expect(mock.stringResult("B")).toBe("B") 250 | } 251 | 252 | @Test 253 | fun stubbingRealObject() { 254 | val notAMock = "" 255 | 256 | /* Expect */ 257 | expectErrorWithMessage("is not a mock!").on { 258 | notAMock.stub { } 259 | } 260 | } 261 | 262 | @Test 263 | fun stubbingTwiceWithCheckArgumentMatchers_throwsException() { 264 | /* Expect */ 265 | expectErrorWithMessage("null").on { 266 | mock { 267 | on { stringResult(check { }) } doReturn "A" 268 | on { stringResult(check { }) } doReturn "B" 269 | } 270 | } 271 | } 272 | 273 | @Test 274 | fun doReturn_withSingleItemList() { 275 | /* Given */ 276 | val mock = mock { 277 | on { stringResult() } doReturnConsecutively listOf("a", "b") 278 | } 279 | 280 | /* Then */ 281 | expect(mock.stringResult()).toBe("a") 282 | expect(mock.stringResult()).toBe("b") 283 | } 284 | 285 | @Test 286 | fun doReturn_throwsNPE() { 287 | assumeFalse(mockMakerInlineEnabled()) 288 | expectErrorWithMessage("look at the stack trace below") on { 289 | 290 | /* When */ 291 | mock { 292 | on { throwsNPE() } doReturn "result" 293 | } 294 | } 295 | } 296 | 297 | @Test 298 | fun doReturn_withGenericIntReturnType_on() { 299 | /* When */ 300 | val mock = mock> { 301 | on { genericMethod() } doReturn 2 302 | } 303 | 304 | /* Then */ 305 | expect(mock.genericMethod()).toBe(2) 306 | } 307 | 308 | @Test 309 | fun doReturn_withGenericIntReturnType_onGeneric() { 310 | /* Given */ 311 | val mock = mock> { 312 | onGeneric { genericMethod() } doReturn 2 313 | } 314 | 315 | /* Then */ 316 | expect(mock.genericMethod()).toBe(2) 317 | } 318 | 319 | @Test 320 | fun doReturn_withGenericNullableReturnType_onGeneric() { 321 | val m = mock> { 322 | onGeneric { nullableReturnType() } doReturn "Test" 323 | } 324 | 325 | expect(m.nullableReturnType()).toBe("Test") 326 | } 327 | 328 | @Test 329 | fun stubbingExistingMock() { 330 | /* Given */ 331 | val mock = mock() 332 | 333 | /* When */ 334 | stubbing(mock) { 335 | on { stringResult() } doReturn "result" 336 | } 337 | 338 | /* Then */ 339 | expect(mock.stringResult()).toBe("result") 340 | } 341 | 342 | @Test 343 | fun testMockitoStackOnUnfinishedStubbing() { 344 | /* Given */ 345 | val mock = mock() 346 | whenever(mock.stringResult()) 347 | 348 | /* When */ 349 | try { 350 | mock.stringResult() 351 | } catch (e: UnfinishedStubbingException) { 352 | /* Then */ 353 | expect(e.message).toContain("Unfinished stubbing detected here:") 354 | expect(e.message).toContain("-> at test.OngoingStubbingTest.testMockitoStackOnUnfinishedStubbing") 355 | } 356 | } 357 | } 358 | -------------------------------------------------------------------------------- /mockito-kotlin/src/main/kotlin/org/mockito/kotlin/Mocking.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018 Niek Haarman 5 | * Copyright (c) 2007 Mockito contributors 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | package org.mockito.kotlin 27 | 28 | import org.mockito.Incubating 29 | import org.mockito.MockSettings 30 | import org.mockito.Mockito 31 | import org.mockito.listeners.InvocationListener 32 | import org.mockito.mock.SerializableMode 33 | import org.mockito.quality.Strictness 34 | import org.mockito.stubbing.Answer 35 | import kotlin.DeprecationLevel.ERROR 36 | import kotlin.reflect.KClass 37 | 38 | /** 39 | * Creates a mock for [T]. 40 | * 41 | * @param extraInterfaces Specifies extra interfaces the mock should implement. 42 | * @param name Specifies mock name. Naming mocks can be helpful for debugging - the name is used in all verification errors. 43 | * @param spiedInstance Specifies the instance to spy on. Makes sense only for spies/partial mocks. 44 | * @param defaultAnswer Specifies default answers to interactions. 45 | * @param serializable Configures the mock to be serializable. 46 | * @param serializableMode Configures the mock to be serializable with a specific serializable mode. 47 | * @param verboseLogging Enables real-time logging of method invocations on this mock. 48 | * @param invocationListeners Registers a listener for method invocations on this mock. The listener is notified every time a method on this mock is called. 49 | * @param stubOnly A stub-only mock does not record method invocations, thus saving memory but disallowing verification of invocations. 50 | * @param useConstructor Mockito attempts to use constructor when creating instance of the mock. 51 | * @param outerInstance Makes it possible to mock non-static inner classes in conjunction with [useConstructor]. 52 | * @param lenient Lenient mocks bypass "strict stubbing" validation. 53 | */ 54 | inline fun mock( 55 | extraInterfaces: Array>? = null, 56 | name: String? = null, 57 | spiedInstance: Any? = null, 58 | defaultAnswer: Answer? = null, 59 | serializable: Boolean = false, 60 | serializableMode: SerializableMode? = null, 61 | verboseLogging: Boolean = false, 62 | invocationListeners: Array? = null, 63 | stubOnly: Boolean = false, 64 | @Incubating useConstructor: UseConstructor? = null, 65 | @Incubating outerInstance: Any? = null, 66 | @Incubating lenient: Boolean = false 67 | ): T { 68 | return Mockito.mock( 69 | T::class.java, 70 | withSettings( 71 | extraInterfaces = extraInterfaces, 72 | name = name, 73 | spiedInstance = spiedInstance, 74 | defaultAnswer = defaultAnswer, 75 | serializable = serializable, 76 | serializableMode = serializableMode, 77 | verboseLogging = verboseLogging, 78 | invocationListeners = invocationListeners, 79 | stubOnly = stubOnly, 80 | useConstructor = useConstructor, 81 | outerInstance = outerInstance, 82 | lenient = lenient 83 | ) 84 | )!! 85 | } 86 | 87 | /** 88 | * Creates a mock for [T], allowing for immediate stubbing. 89 | * 90 | * @param extraInterfaces Specifies extra interfaces the mock should implement. 91 | * @param name Specifies mock name. Naming mocks can be helpful for debugging - the name is used in all verification errors. 92 | * @param spiedInstance Specifies the instance to spy on. Makes sense only for spies/partial mocks. 93 | * @param defaultAnswer Specifies default answers to interactions. 94 | * @param serializable Configures the mock to be serializable. 95 | * @param serializableMode Configures the mock to be serializable with a specific serializable mode. 96 | * @param verboseLogging Enables real-time logging of method invocations on this mock. 97 | * @param invocationListeners Registers a listener for method invocations on this mock. The listener is notified every time a method on this mock is called. 98 | * @param stubOnly A stub-only mock does not record method invocations, thus saving memory but disallowing verification of invocations. 99 | * @param useConstructor Mockito attempts to use constructor when creating instance of the mock. 100 | * @param outerInstance Makes it possible to mock non-static inner classes in conjunction with [useConstructor]. 101 | * @param lenient Lenient mocks bypass "strict stubbing" validation. 102 | */ 103 | inline fun mock( 104 | extraInterfaces: Array>? = null, 105 | name: String? = null, 106 | spiedInstance: Any? = null, 107 | defaultAnswer: Answer? = null, 108 | serializable: Boolean = false, 109 | serializableMode: SerializableMode? = null, 110 | verboseLogging: Boolean = false, 111 | invocationListeners: Array? = null, 112 | stubOnly: Boolean = false, 113 | @Incubating useConstructor: UseConstructor? = null, 114 | @Incubating outerInstance: Any? = null, 115 | @Incubating lenient: Boolean = false, 116 | stubbing: KStubbing.(T) -> Unit 117 | ): T { 118 | return Mockito.mock( 119 | T::class.java, 120 | withSettings( 121 | extraInterfaces = extraInterfaces, 122 | name = name, 123 | spiedInstance = spiedInstance, 124 | defaultAnswer = defaultAnswer, 125 | serializable = serializable, 126 | serializableMode = serializableMode, 127 | verboseLogging = verboseLogging, 128 | invocationListeners = invocationListeners, 129 | stubOnly = stubOnly, 130 | useConstructor = useConstructor, 131 | outerInstance = outerInstance, 132 | lenient = lenient 133 | ) 134 | ).apply { KStubbing(this).stubbing(this) }!! 135 | } 136 | 137 | /** 138 | * Allows mock creation with additional mock settings. 139 | * See [MockSettings]. 140 | * 141 | * @param extraInterfaces Specifies extra interfaces the mock should implement. 142 | * @param name Specifies mock name. Naming mocks can be helpful for debugging - the name is used in all verification errors. 143 | * @param spiedInstance Specifies the instance to spy on. Makes sense only for spies/partial mocks. 144 | * @param defaultAnswer Specifies default answers to interactions. 145 | * @param serializable Configures the mock to be serializable. 146 | * @param serializableMode Configures the mock to be serializable with a specific serializable mode. 147 | * @param verboseLogging Enables real-time logging of method invocations on this mock. 148 | * @param invocationListeners Registers a listener for method invocations on this mock. The listener is notified every time a method on this mock is called. 149 | * @param stubOnly A stub-only mock does not record method invocations, thus saving memory but disallowing verification of invocations. 150 | * @param useConstructor Mockito attempts to use constructor when creating instance of the mock. 151 | * @param outerInstance Makes it possible to mock non-static inner classes in conjunction with [useConstructor]. 152 | * @param lenient Lenient mocks bypass "strict stubbing" validation. 153 | */ 154 | fun withSettings( 155 | extraInterfaces: Array>? = null, 156 | name: String? = null, 157 | spiedInstance: Any? = null, 158 | defaultAnswer: Answer? = null, 159 | serializable: Boolean = false, 160 | serializableMode: SerializableMode? = null, 161 | verboseLogging: Boolean = false, 162 | invocationListeners: Array? = null, 163 | stubOnly: Boolean = false, 164 | @Incubating useConstructor: UseConstructor? = null, 165 | @Incubating outerInstance: Any? = null, 166 | @Incubating lenient: Boolean = false 167 | ): MockSettings = Mockito.withSettings().apply { 168 | extraInterfaces?.let { extraInterfaces(*it.map { it.java }.toTypedArray()) } 169 | name?.let { name(it) } 170 | spiedInstance?.let { spiedInstance(it) } 171 | defaultAnswer?.let { defaultAnswer(it) } 172 | if (serializable) serializable() 173 | serializableMode?.let { serializable(it) } 174 | if (verboseLogging) verboseLogging() 175 | invocationListeners?.let { invocationListeners(*it) } 176 | if (stubOnly) stubOnly() 177 | useConstructor?.let { useConstructor(*it.args) } 178 | outerInstance?.let { outerInstance(it) } 179 | if (lenient) strictness(Strictness.LENIENT) 180 | } 181 | 182 | class UseConstructor private constructor(val args: Array) { 183 | 184 | companion object { 185 | 186 | /** Invokes the parameterless constructor. */ 187 | fun parameterless() = UseConstructor(emptyArray()) 188 | 189 | /** Invokes a constructor with given arguments. */ 190 | fun withArguments(vararg arguments: Any): UseConstructor { 191 | return UseConstructor(arguments.asList().toTypedArray()) 192 | } 193 | } 194 | } 195 | 196 | @Deprecated( 197 | "Use mock() with optional arguments instead.", 198 | ReplaceWith("mock(defaultAnswer = a)"), 199 | level = ERROR 200 | ) 201 | inline fun mock(a: Answer): T = mock(defaultAnswer = a) 202 | 203 | @Deprecated( 204 | "Use mock() with optional arguments instead.", 205 | ReplaceWith("mock(name = s)"), 206 | level = ERROR 207 | ) 208 | inline fun mock(s: String): T = mock(name = s) 209 | 210 | @Suppress("DeprecatedCallableAddReplaceWith") 211 | @Deprecated("Use mock() with optional arguments instead.", level = ERROR) 212 | inline fun mock(s: MockSettings): T = Mockito.mock(T::class.java, s)!! 213 | -------------------------------------------------------------------------------- /tests/src/test/kotlin/test/MockingTest.kt: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import com.nhaarman.expect.expect 4 | import com.nhaarman.expect.expectErrorWithMessage 5 | import com.nhaarman.expect.fail 6 | import org.mockito.kotlin.UseConstructor.Companion.parameterless 7 | import org.mockito.kotlin.UseConstructor.Companion.withArguments 8 | import org.mockito.kotlin.doReturn 9 | import org.mockito.kotlin.mock 10 | import org.mockito.kotlin.verify 11 | import org.mockito.kotlin.whenever 12 | import org.junit.Test 13 | import org.mockito.Mockito 14 | import org.mockito.exceptions.verification.WantedButNotInvoked 15 | import org.mockito.invocation.DescribedInvocation 16 | import org.mockito.kotlin.argumentCaptor 17 | import org.mockito.listeners.InvocationListener 18 | import org.mockito.mock.SerializableMode.BASIC 19 | import java.io.PrintStream 20 | import java.io.Serializable 21 | import java.util.* 22 | 23 | class MockingTest : TestBase() { 24 | 25 | private lateinit var propertyInterfaceVariable: MyInterface 26 | private lateinit var propertyClassVariable: MyClass 27 | 28 | @Test 29 | fun localInterfaceValue() { 30 | /* When */ 31 | val instance: MyInterface = mock() 32 | 33 | /* Then */ 34 | expect(instance).toNotBeNull() 35 | } 36 | 37 | @Test 38 | fun propertyInterfaceVariable() { 39 | /* When */ 40 | propertyInterfaceVariable = mock() 41 | 42 | /* Then */ 43 | expect(propertyInterfaceVariable).toNotBeNull() 44 | } 45 | 46 | @Test 47 | fun localClassValue() { 48 | /* When */ 49 | val instance: MyClass = mock() 50 | 51 | /* Then */ 52 | expect(instance).toNotBeNull() 53 | } 54 | 55 | @Test 56 | fun propertyClassVariable() { 57 | /* When */ 58 | propertyClassVariable = mock() 59 | 60 | /* Then */ 61 | expect(propertyClassVariable).toNotBeNull() 62 | } 63 | 64 | @Test 65 | fun untypedVariable() { 66 | /* When */ 67 | val instance = mock() 68 | 69 | expect(instance).toNotBeNull() 70 | } 71 | 72 | @Test 73 | fun deepStubs() { 74 | val cal: Calendar = mock(defaultAnswer = Mockito.RETURNS_DEEP_STUBS) 75 | whenever(cal.time.time).thenReturn(123L) 76 | expect(cal.time.time).toBe(123L) 77 | } 78 | 79 | @Test 80 | fun testMockStubbing_lambda() { 81 | /* Given */ 82 | val mock = mock() { 83 | on { stringResult() } doReturn "A" 84 | } 85 | 86 | /* When */ 87 | val result = mock.stringResult() 88 | 89 | /* Then */ 90 | expect(result).toBe("A") 91 | } 92 | 93 | @Test 94 | fun testMockStubbing_normalOverridesLambda() { 95 | /* Given */ 96 | val mock = mock() { 97 | on { stringResult() }.doReturn("A") 98 | } 99 | whenever(mock.stringResult()).thenReturn("B") 100 | 101 | /* When */ 102 | val result = mock.stringResult() 103 | 104 | /* Then */ 105 | expect(result).toBe("B") 106 | } 107 | 108 | @Test 109 | fun mock_withCustomDefaultAnswer_parameterName() { 110 | /* Given */ 111 | val mock = mock(defaultAnswer = Mockito.RETURNS_SELF) 112 | 113 | /* When */ 114 | val result = mock.builderMethod() 115 | 116 | /* Then */ 117 | expect(result).toBe(mock) 118 | } 119 | 120 | @Test 121 | fun mock_withSettingsAPI_extraInterfaces() { 122 | /* Given */ 123 | val mock = mock( 124 | extraInterfaces = arrayOf(ExtraInterface::class) 125 | ) 126 | 127 | /* Then */ 128 | expect(mock).toBeInstanceOf() 129 | } 130 | 131 | @Test 132 | fun mock_withSettingsAPI_name() { 133 | /* Given */ 134 | val mock = mock(name = "myName") 135 | 136 | /* When */ 137 | expectErrorWithMessage("myName.stringResult()") on { 138 | verify(mock).stringResult() 139 | } 140 | } 141 | 142 | @Test 143 | fun mock_withSettingsAPI_defaultAnswer() { 144 | /* Given */ 145 | val mock = mock(defaultAnswer = Mockito.RETURNS_MOCKS) 146 | 147 | /* When */ 148 | val result = mock.nonDefaultReturnType() 149 | 150 | /* Then */ 151 | expect(result).toNotBeNull() 152 | } 153 | 154 | @Test 155 | fun mock_withSettingsAPI_serializable() { 156 | /* Given */ 157 | val mock = mock(serializable = true) 158 | 159 | /* Then */ 160 | expect(mock).toBeInstanceOf() 161 | } 162 | 163 | @Test 164 | fun mock_withSettingsAPI_serializableMode() { 165 | /* Given */ 166 | val mock = mock(serializableMode = BASIC) 167 | 168 | /* Then */ 169 | expect(mock).toBeInstanceOf() 170 | } 171 | 172 | @Test 173 | fun mock_withSettingsAPI_verboseLogging() { 174 | /* Given */ 175 | val out = mock() 176 | System.setOut(out) 177 | val mock = mock(verboseLogging = true) 178 | 179 | try { 180 | /* When */ 181 | verify(mock).stringResult() 182 | fail("Expected an exception") 183 | } catch (e: WantedButNotInvoked) { 184 | /* Then */ 185 | argumentCaptor().apply { 186 | verify(out).println(capture()) 187 | expect(lastValue.toString()).toBe("methods.stringResult();") 188 | } 189 | } 190 | } 191 | 192 | @Test 193 | fun mock_withSettingsAPI_invocationListeners() { 194 | /* Given */ 195 | var bool = false 196 | val mock = mock(invocationListeners = arrayOf(InvocationListener { bool = true })) 197 | 198 | /* When */ 199 | mock.stringResult() 200 | 201 | /* Then */ 202 | expect(bool).toHold() 203 | } 204 | 205 | @Test 206 | fun mock_withSettingsAPI_stubOnly() { 207 | /* Given */ 208 | val mock = mock(stubOnly = true) 209 | 210 | /* Expect */ 211 | expectErrorWithMessage("is a stubOnly() mock") on { 212 | 213 | /* When */ 214 | verify(mock).stringResult() 215 | } 216 | } 217 | 218 | @Test 219 | fun mock_withSettingsAPI_useConstructor() { 220 | /* Given */ 221 | expectErrorWithMessage("Unable to create mock instance of type ") on { 222 | mock(useConstructor = parameterless()) {} 223 | } 224 | } 225 | 226 | @Test 227 | fun mock_withSettingsAPI_useConstructorWithArguments_failing() { 228 | /* Given */ 229 | expectErrorWithMessage("Unable to create mock instance of type ") on { 230 | mock(useConstructor = withArguments("Test")) {} 231 | } 232 | } 233 | 234 | @Test 235 | fun mock_withSettingsAPI_useConstructorWithArguments() { 236 | /* When */ 237 | val result = mock(useConstructor = withArguments("Test")) {} 238 | 239 | /* Then */ 240 | expect(result).toNotBeNull() 241 | } 242 | 243 | @Test 244 | fun mockStubbing_withSettingsAPI_extraInterfaces() { 245 | /* Given */ 246 | val mock = mock(extraInterfaces = arrayOf(ExtraInterface::class)) {} 247 | 248 | /* Then */ 249 | expect(mock).toBeInstanceOf() 250 | } 251 | 252 | @Test 253 | fun mockStubbing_withSettingsAPI_name() { 254 | /* Given */ 255 | val mock = mock(name = "myName") {} 256 | 257 | /* When */ 258 | expectErrorWithMessage("myName.stringResult()") on { 259 | verify(mock).stringResult() 260 | } 261 | } 262 | 263 | @Test 264 | fun mockStubbing_withSettingsAPIAndStubbing_name() { 265 | /* Given */ 266 | val mock = mock(name = "myName") { 267 | on { nullableStringResult() } doReturn "foo" 268 | } 269 | 270 | /* When */ 271 | val result = mock.nullableStringResult() 272 | 273 | /* Then */ 274 | expect(result).toBe("foo") 275 | } 276 | 277 | @Test 278 | fun mockStubbing_withSettingsAPI_defaultAnswer() { 279 | /* Given */ 280 | val mock = mock(defaultAnswer = Mockito.RETURNS_MOCKS) {} 281 | 282 | /* When */ 283 | val result = mock.nonDefaultReturnType() 284 | 285 | /* Then */ 286 | expect(result).toNotBeNull() 287 | } 288 | 289 | @Test 290 | fun mockStubbing_withSettingsAPI_serializable() { 291 | /* Given */ 292 | val mock = mock(serializable = true) {} 293 | 294 | /* Then */ 295 | expect(mock).toBeInstanceOf() 296 | } 297 | 298 | @Test 299 | fun mockStubbing_withSettingsAPI_serializableMode() { 300 | /* Given */ 301 | val mock = mock(serializableMode = BASIC) {} 302 | 303 | /* Then */ 304 | expect(mock).toBeInstanceOf() 305 | } 306 | 307 | @Test 308 | fun mockStubbing_withSettingsAPI_verboseLogging() { 309 | /* Given */ 310 | val out = mock() 311 | System.setOut(out) 312 | val mock = mock(verboseLogging = true) {} 313 | 314 | try { 315 | /* When */ 316 | verify(mock).stringResult() 317 | fail("Expected an exception") 318 | } catch (e: WantedButNotInvoked) { 319 | /* Then */ 320 | argumentCaptor().apply { 321 | verify(out).println(capture()) 322 | expect(lastValue.toString()).toBe("methods.stringResult();") 323 | } 324 | } 325 | } 326 | 327 | @Test 328 | fun mockStubbing_withSettingsAPI_invocationListeners() { 329 | /* Given */ 330 | var bool = false 331 | val mock = mock(invocationListeners = arrayOf(InvocationListener { bool = true })) {} 332 | 333 | /* When */ 334 | mock.stringResult() 335 | 336 | /* Then */ 337 | expect(bool).toHold() 338 | } 339 | 340 | @Test 341 | fun mockStubbing_withSettingsAPI_stubOnly() { 342 | /* Given */ 343 | val mock = mock(stubOnly = true) {} 344 | 345 | /* Expect */ 346 | expectErrorWithMessage("is a stubOnly() mock") on { 347 | 348 | /* When */ 349 | verify(mock).stringResult() 350 | } 351 | } 352 | 353 | @Test 354 | fun mockStubbing_withSettingsAPI_useConstructor() { 355 | /* Given */ 356 | expectErrorWithMessage("Unable to create mock instance of type ") on { 357 | mock(useConstructor = parameterless()) {} 358 | } 359 | } 360 | 361 | private interface MyInterface 362 | private open class MyClass 363 | } 364 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 30 | 276 | -------------------------------------------------------------------------------- /mockito-kotlin/src/test/kotlin/test/CoroutinesTest.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("EXPERIMENTAL_FEATURE_WARNING") 2 | 3 | package test 4 | 5 | import com.nhaarman.expect.expect 6 | import kotlinx.coroutines.Dispatchers 7 | import kotlinx.coroutines.delay 8 | import kotlinx.coroutines.runBlocking 9 | import kotlinx.coroutines.withContext 10 | import kotlinx.coroutines.* 11 | import kotlinx.coroutines.channels.actor 12 | import org.junit.Assert.assertEquals 13 | import org.junit.Assert.assertThrows 14 | import org.junit.Test 15 | import org.mockito.InOrder 16 | import org.mockito.kotlin.* 17 | import java.util.* 18 | 19 | class CoroutinesTest { 20 | 21 | @Test 22 | fun stubbingSuspending() { 23 | /* Given */ 24 | val m = mock { 25 | onBlocking { suspending() } doReturn 42 26 | } 27 | 28 | /* When */ 29 | val result = runBlocking { m.suspending() } 30 | 31 | /* Then */ 32 | expect(result).toBe(42) 33 | } 34 | 35 | @Test 36 | fun stubbingSuspending_usingSuspendingFunction() { 37 | /* Given */ 38 | val m = mock { 39 | onBlocking { suspending() } doReturn runBlocking { SomeClass().result(42) } 40 | } 41 | 42 | /* When */ 43 | val result = runBlocking { m.suspending() } 44 | 45 | /* Then */ 46 | expect(result).toBe(42) 47 | } 48 | 49 | @Test 50 | fun stubbingSuspending_runBlocking() = runBlocking { 51 | /* Given */ 52 | val m = mock { 53 | onBlocking { suspending() } doReturn 42 54 | } 55 | 56 | /* When */ 57 | val result = m.suspending() 58 | 59 | /* Then */ 60 | expect(result).toBe(42) 61 | } 62 | 63 | @Test 64 | fun stubbingSuspending_wheneverBlocking() { 65 | /* Given */ 66 | val m: SomeInterface = mock() 67 | wheneverBlocking { m.suspending() } 68 | .doReturn(42) 69 | 70 | /* When */ 71 | val result = runBlocking { m.suspending() } 72 | 73 | /* Then */ 74 | expect(result).toBe(42) 75 | } 76 | 77 | @Test 78 | fun stubbingSuspending_doReturn() { 79 | /* Given */ 80 | val m = spy(SomeClass()) 81 | doReturn(10) 82 | .wheneverBlocking(m) { 83 | delaying() 84 | } 85 | 86 | /* When */ 87 | val result = runBlocking { m.delaying() } 88 | 89 | /* Then */ 90 | expect(result).toBe(10) 91 | } 92 | 93 | @Test 94 | fun stubbingNonSuspending() { 95 | /* Given */ 96 | val m = mock { 97 | onBlocking { nonsuspending() } doReturn 42 98 | } 99 | 100 | /* When */ 101 | val result = m.nonsuspending() 102 | 103 | /* Then */ 104 | expect(result).toBe(42) 105 | } 106 | 107 | @Test 108 | fun stubbingNonSuspending_runBlocking() = runBlocking { 109 | /* Given */ 110 | val m = mock { 111 | onBlocking { nonsuspending() } doReturn 42 112 | } 113 | 114 | /* When */ 115 | val result = m.nonsuspending() 116 | 117 | /* Then */ 118 | expect(result).toBe(42) 119 | } 120 | 121 | @Test 122 | fun delayingResult() { 123 | /* Given */ 124 | val m = SomeClass() 125 | 126 | /* When */ 127 | val result = runBlocking { m.delaying() } 128 | 129 | /* Then */ 130 | expect(result).toBe(42) 131 | } 132 | 133 | @Test 134 | fun delayingResult_runBlocking() = runBlocking { 135 | /* Given */ 136 | val m = SomeClass() 137 | 138 | /* When */ 139 | val result = m.delaying() 140 | 141 | /* Then */ 142 | expect(result).toBe(42) 143 | } 144 | 145 | @Test 146 | fun verifySuspendFunctionCalled() { 147 | /* Given */ 148 | val m = mock() 149 | 150 | /* When */ 151 | runBlocking { m.suspending() } 152 | 153 | /* Then */ 154 | runBlocking { verify(m).suspending() } 155 | } 156 | 157 | @Test 158 | fun verifySuspendFunctionCalled_runBlocking() = runBlocking { 159 | val m = mock() 160 | 161 | m.suspending() 162 | 163 | verify(m).suspending() 164 | } 165 | 166 | @Test 167 | fun verifySuspendFunctionCalled_verifyBlocking() { 168 | val m = mock() 169 | 170 | runBlocking { m.suspending() } 171 | 172 | verifyBlocking(m) { suspending() } 173 | } 174 | 175 | @Test 176 | fun verifyAtLeastOnceSuspendFunctionCalled_verifyBlocking() { 177 | val m = mock() 178 | 179 | runBlocking { m.suspending() } 180 | runBlocking { m.suspending() } 181 | 182 | verifyBlocking(m, atLeastOnce()) { suspending() } 183 | } 184 | 185 | @Test 186 | fun verifySuspendMethod() = runBlocking { 187 | val testSubject: SomeInterface = mock() 188 | 189 | testSubject.suspending() 190 | 191 | inOrder(testSubject) { 192 | verify(testSubject).suspending() 193 | } 194 | } 195 | 196 | @Test 197 | fun answerWithSuspendFunction() = runBlocking { 198 | val fixture: SomeInterface = mock() 199 | 200 | whenever(fixture.suspendingWithArg(any())).doSuspendableAnswer { 201 | withContext(Dispatchers.Default) { it.getArgument(0) } 202 | } 203 | 204 | assertEquals(5, fixture.suspendingWithArg(5)) 205 | } 206 | 207 | @Test 208 | fun inplaceAnswerWithSuspendFunction() = runBlocking { 209 | val fixture: SomeInterface = mock { 210 | onBlocking { suspendingWithArg(any()) } doSuspendableAnswer { 211 | withContext(Dispatchers.Default) { it.getArgument(0) } 212 | } 213 | } 214 | 215 | assertEquals(5, fixture.suspendingWithArg(5)) 216 | } 217 | 218 | @Test 219 | fun callFromSuspendFunction() = runBlocking { 220 | val fixture: SomeInterface = mock() 221 | 222 | whenever(fixture.suspendingWithArg(any())).doSuspendableAnswer { 223 | withContext(Dispatchers.Default) { it.getArgument(0) } 224 | } 225 | 226 | val result = async { 227 | val answer = fixture.suspendingWithArg(5) 228 | 229 | Result.success(answer) 230 | } 231 | 232 | assertEquals(5, result.await().getOrThrow()) 233 | } 234 | 235 | @Test 236 | fun callFromActor() = runBlocking { 237 | val fixture: SomeInterface = mock() 238 | 239 | whenever(fixture.suspendingWithArg(any())).doSuspendableAnswer { 240 | withContext(Dispatchers.Default) { it.getArgument(0) } 241 | } 242 | 243 | val actor = actor> { 244 | for (element in channel) { 245 | fixture.suspendingWithArg(element.get()) 246 | } 247 | } 248 | 249 | actor.send(Optional.of(10)) 250 | actor.close() 251 | 252 | verify(fixture).suspendingWithArg(10) 253 | 254 | Unit 255 | } 256 | 257 | @Test 258 | fun answerWithSuspendFunctionWithoutArgs() = runBlocking { 259 | val fixture: SomeInterface = mock() 260 | 261 | whenever(fixture.suspending()).doSuspendableAnswer { 262 | withContext(Dispatchers.Default) { 42 } 263 | } 264 | 265 | assertEquals(42, fixture.suspending()) 266 | } 267 | 268 | @Test 269 | fun willAnswerWithControlledSuspend() = runBlocking { 270 | val fixture: SomeInterface = mock() 271 | 272 | val job = Job() 273 | 274 | whenever(fixture.suspending()).doSuspendableAnswer { 275 | job.join() 276 | 5 277 | } 278 | 279 | val asyncTask = async { 280 | fixture.suspending() 281 | } 282 | 283 | job.complete() 284 | 285 | withTimeout(100) { 286 | assertEquals(5, asyncTask.await()) 287 | } 288 | } 289 | 290 | @Test 291 | fun inOrderRemainsCompatible() { 292 | /* Given */ 293 | val fixture: SomeInterface = mock() 294 | 295 | /* When */ 296 | val inOrder = inOrder(fixture) 297 | 298 | /* Then */ 299 | expect(inOrder).toBeInstanceOf() 300 | } 301 | 302 | @Test 303 | fun inOrderSuspendingCalls() { 304 | /* Given */ 305 | val fixtureOne: SomeInterface = mock() 306 | val fixtureTwo: SomeInterface = mock() 307 | 308 | /* When */ 309 | runBlocking { 310 | fixtureOne.suspending() 311 | fixtureTwo.suspending() 312 | } 313 | 314 | /* Then */ 315 | val inOrder = inOrder(fixtureOne, fixtureTwo) 316 | inOrder.verifyBlocking(fixtureOne) { suspending() } 317 | inOrder.verifyBlocking(fixtureTwo) { suspending() } 318 | } 319 | 320 | @Test 321 | fun inOrderSuspendingCallsFailure() { 322 | /* Given */ 323 | val fixtureOne: SomeInterface = mock() 324 | val fixtureTwo: SomeInterface = mock() 325 | 326 | /* When */ 327 | runBlocking { 328 | fixtureOne.suspending() 329 | fixtureTwo.suspending() 330 | } 331 | 332 | /* Then */ 333 | val inOrder = inOrder(fixtureOne, fixtureTwo) 334 | inOrder.verifyBlocking(fixtureTwo) { suspending() } 335 | assertThrows(AssertionError::class.java) { 336 | inOrder.verifyBlocking(fixtureOne) { suspending() } 337 | } 338 | } 339 | 340 | @Test 341 | fun inOrderBlockSuspendingCalls() { 342 | /* Given */ 343 | val fixtureOne: SomeInterface = mock() 344 | val fixtureTwo: SomeInterface = mock() 345 | 346 | /* When */ 347 | runBlocking { 348 | fixtureOne.suspending() 349 | fixtureTwo.suspending() 350 | } 351 | 352 | /* Then */ 353 | inOrder(fixtureOne, fixtureTwo) { 354 | verifyBlocking(fixtureOne) { suspending() } 355 | verifyBlocking(fixtureTwo) { suspending() } 356 | } 357 | } 358 | 359 | @Test 360 | fun inOrderBlockSuspendingCallsFailure() { 361 | /* Given */ 362 | val fixtureOne: SomeInterface = mock() 363 | val fixtureTwo: SomeInterface = mock() 364 | 365 | /* When */ 366 | runBlocking { 367 | fixtureOne.suspending() 368 | fixtureTwo.suspending() 369 | } 370 | 371 | /* Then */ 372 | inOrder(fixtureOne, fixtureTwo) { 373 | verifyBlocking(fixtureTwo) { suspending() } 374 | assertThrows(AssertionError::class.java) { 375 | verifyBlocking(fixtureOne) { suspending() } 376 | } 377 | } 378 | } 379 | 380 | @Test 381 | fun inOrderOnObjectSuspendingCalls() { 382 | /* Given */ 383 | val fixture: SomeInterface = mock() 384 | 385 | /* When */ 386 | runBlocking { 387 | fixture.suspendingWithArg(1) 388 | fixture.suspendingWithArg(2) 389 | } 390 | 391 | /* Then */ 392 | fixture.inOrder { 393 | verifyBlocking { suspendingWithArg(1) } 394 | verifyBlocking { suspendingWithArg(2) } 395 | } 396 | } 397 | 398 | @Test 399 | fun inOrderOnObjectSuspendingCallsFailure() { 400 | /* Given */ 401 | val fixture: SomeInterface = mock() 402 | 403 | /* When */ 404 | runBlocking { 405 | fixture.suspendingWithArg(1) 406 | fixture.suspendingWithArg(2) 407 | } 408 | 409 | /* Then */ 410 | fixture.inOrder { 411 | verifyBlocking { suspendingWithArg(2) } 412 | assertThrows(AssertionError::class.java) { 413 | verifyBlocking { suspendingWithArg(1) } 414 | } 415 | } 416 | } 417 | } 418 | 419 | interface SomeInterface { 420 | 421 | suspend fun suspending(): Int 422 | suspend fun suspendingWithArg(arg: Int): Int 423 | fun nonsuspending(): Int 424 | } 425 | 426 | open class SomeClass { 427 | 428 | suspend fun result(r: Int) = withContext(Dispatchers.Default) { r } 429 | 430 | open suspend fun delaying() = withContext(Dispatchers.Default) { 431 | delay(100) 432 | 42 433 | } 434 | } 435 | --------------------------------------------------------------------------------