├── .github ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── ci.yml ├── .gitignore ├── .idea ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── copyright │ ├── MIT.xml │ └── profiles_settings.xml └── inspectionProfiles │ └── Project_Default.xml ├── LICENSE ├── README.md ├── RELEASING.md ├── build.gradle ├── gradle.properties ├── gradle ├── publishing.gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── mockito-kotlin ├── build.gradle └── src │ ├── main │ └── kotlin │ │ └── org │ │ └── mockito │ │ └── kotlin │ │ ├── AdditionalMatchers.kt │ │ ├── ArgumentCaptor.kt │ │ ├── BDDMockito.kt │ │ ├── KInOrder.kt │ │ ├── KInvocationOnMock.kt │ │ ├── KStubbing.kt │ │ ├── LenientStubber.kt │ │ ├── Matchers.kt │ │ ├── Mocking.kt │ │ ├── Mockito.kt │ │ ├── MockitoKotlinException.kt │ │ ├── OngoingStubbing.kt │ │ ├── Spying.kt │ │ ├── Stubber.kt │ │ ├── Verification.kt │ │ ├── VerifyScope.kt │ │ └── internal │ │ ├── CreateInstance.kt │ │ ├── KAnswer.kt │ │ ├── KInOrderDecorator.kt │ │ └── SuspendableAnswer.kt │ └── test │ └── kotlin │ ├── org │ └── mockito │ │ └── kotlin │ │ └── BDDMockitoKtTest.kt │ └── test │ └── CoroutinesTest.kt ├── ops ├── mockMakerInline.sh └── org.mockito.plugins.MockMaker ├── settings.gradle ├── tests ├── README.md ├── build.gradle ├── gradle.properties ├── settings.gradle └── src │ └── test │ └── kotlin │ └── test │ ├── AdditionalMatchersTest.kt │ ├── ArgumentCaptorTest.kt │ ├── BDDMockitoTest.kt │ ├── Classes.kt │ ├── EqTest.kt │ ├── LenientStubberTest.kt │ ├── MatchersTest.kt │ ├── MockMaker.kt │ ├── MockingTest.kt │ ├── OngoingStubbingTest.kt │ ├── SpyTest.kt │ ├── StubberTest.kt │ ├── TestBase.kt │ ├── VerificationTest.kt │ ├── VerifyTest.kt │ ├── createinstance │ └── NullCasterTest.kt │ └── inline │ └── UsingMockMakerInlineTest.kt └── version.properties /.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 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.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/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 30 | 276 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/copyright/MIT.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /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. -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "org.gradle.base" 3 | id "org.shipkit.shipkit-changelog" version "1.2.0" 4 | id "org.shipkit.shipkit-github-release" version "1.2.0" 5 | id "org.shipkit.shipkit-auto-version" version "1.2.2" 6 | id "io.github.gradle-nexus.publish-plugin" version "1.3.0" 7 | id "org.jetbrains.kotlin.jvm" version "1.9.20" apply false 8 | id "org.jetbrains.dokka" version "1.9.10" apply false 9 | } 10 | 11 | def test = tasks.register("test") { 12 | dependsOn gradle.includedBuild("tests").task(":test") 13 | } 14 | tasks.named("check") { 15 | dependsOn test 16 | } 17 | 18 | tasks.named("generateChangelog") { 19 | previousRevision = project.ext.'shipkit-auto-version.previous-version' 20 | githubToken = System.getenv("GITHUB_TOKEN") 21 | repository = "mockito/mockito-kotlin" 22 | releaseTag = project.version 23 | } 24 | 25 | tasks.named("githubRelease") { 26 | def genTask = tasks.named("generateChangelog").get() 27 | dependsOn genTask 28 | repository = genTask.repository 29 | changelog = genTask.outputFile 30 | githubToken = System.getenv("GITHUB_TOKEN") 31 | newTagRevision = System.getenv("GITHUB_SHA") 32 | releaseTag = project.version 33 | releaseName = project.version 34 | } 35 | 36 | // Will be used to handle Sonatype staging repositories. 37 | group = 'org.mockito.kotlin' 38 | 39 | nexusPublishing { 40 | repositories { 41 | if (System.getenv("NEXUS_TOKEN_PWD")) { 42 | sonatype { 43 | // Publishing to: https://s01.oss.sonatype.org (faster instance) 44 | nexusUrl = uri("https://s01.oss.sonatype.org/service/local/") 45 | snapshotRepositoryUrl = uri("https://s01.oss.sonatype.org/content/repositories/snapshots/") 46 | 47 | username = System.getenv("NEXUS_TOKEN_USER") 48 | password = System.getenv("NEXUS_TOKEN_PWD") 49 | } 50 | } 51 | } 52 | } 53 | 54 | def isSnapshot = version.endsWith("-SNAPSHOT") 55 | 56 | if (isSnapshot) { 57 | println "Building a -SNAPSHOT version (Github release and Maven Central tasks are skipped)" 58 | tasks.named("githubRelease") { 59 | //snapshot versions do not produce changelog / Github releases 60 | enabled = false 61 | } 62 | tasks.named("closeAndReleaseStagingRepository") { 63 | //snapshot binaries are available in Sonatype without the need to close the staging repo 64 | enabled = false 65 | } 66 | } 67 | 68 | tasks.register("releaseSummary") { 69 | doLast { 70 | if (isSnapshot) { 71 | println "RELEASE SUMMARY\n" + 72 | " SNAPSHOTS released to: https://s01.oss.sonatype.org/content/repositories/snapshots/org/mockito/kotlin/mockito-kotlin\n" + 73 | " Release to Maven Central: SKIPPED FOR SNAPSHOTS\n" + 74 | " Github releases: SKIPPED FOR SNAPSHOTS" 75 | } else { 76 | println "RELEASE SUMMARY\n" + 77 | " Release to Maven Central (available after delay): https://repo1.maven.org/maven2/org/mockito/kotlin/mockito-kotlin/\n" + 78 | " Github releases: https://github.com/mockito/mockito-kotlin/releases" 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | isRelease=false 2 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mockito/mockito-kotlin/f97dd1a8ac1e42c8843a17b6fb51ec1264929b7d/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | implementation "org.jetbrains.kotlin:kotlin-reflect:1.9.20" 20 | 21 | api "org.mockito:mockito-core:5.17.0" 22 | 23 | testImplementation 'junit:junit:4.13.2' 24 | testImplementation 'com.nhaarman:expect.kt:1.0.1' 25 | 26 | testImplementation "org.jetbrains.kotlin:kotlin-stdlib" 27 | testImplementation "org.jetbrains.kotlin:kotlin-test" 28 | testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.0' 29 | 30 | testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.0" 31 | } 32 | 33 | dokkaHtml.configure { 34 | outputDirectory.set(file("$buildDir/javadoc")) 35 | 36 | dokkaSourceSets { 37 | named("main") { 38 | localDirectory.set(file("src/main/kotlin")) 39 | remoteUrl.set(new URL("https://github.com/nhaarman/mockito-kotlin/tree/master/mockito-kotlin/src/main/kotlin")) 40 | remoteLineSuffix.set("#L") 41 | } 42 | } 43 | } 44 | 45 | tasks.withType(KotlinCompile).configureEach { 46 | compilerOptions { 47 | jvmTarget.set(JvmTarget.JVM_11) 48 | targetCompatibility = "11" 49 | } 50 | } 51 | 52 | javadoc.dependsOn dokkaHtml 53 | -------------------------------------------------------------------------------- /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 | 30 | /** comparable argument greater than or equal the given value. */ 31 | inline fun > geq(value: T): T { 32 | return AdditionalMatchers.geq(value) ?: createInstance() 33 | } 34 | 35 | /** comparable argument greater than or equal to the given value. */ 36 | inline fun > leq(value: T): T { 37 | return AdditionalMatchers.leq(value) ?: createInstance() 38 | } 39 | 40 | /** comparable argument greater than the given value. */ 41 | inline fun > gt(value: T): T { 42 | return AdditionalMatchers.gt(value) ?: createInstance() 43 | } 44 | 45 | /** comparable argument less than the given value. */ 46 | inline fun > lt(value: T): T { 47 | return AdditionalMatchers.lt(value) ?: createInstance() 48 | } 49 | 50 | /** comparable argument equals to the given value according to their compareTo method. */ 51 | inline fun > cmpEq(value: T): T { 52 | return AdditionalMatchers.cmpEq(value) ?: createInstance() 53 | } 54 | 55 | /** 56 | * Any array argument that is equal to the given array, i.e. it has to have the same type, length, 57 | * and each element has to be equal. 58 | */ 59 | inline fun aryEq(value: Array): Array { 60 | return AdditionalMatchers.aryEq(value) ?: createInstance() 61 | } 62 | 63 | /** 64 | * short array argument that is equal to the given array, i.e. it has to have the same length, and 65 | * each element has to be equal. 66 | */ 67 | fun aryEq(value: ShortArray): ShortArray { 68 | return AdditionalMatchers.aryEq(value) ?: createInstance() 69 | } 70 | 71 | /** 72 | * long array argument that is equal to the given array, i.e. it has to have the same length, and 73 | * each element has to be equal. 74 | */ 75 | fun aryEq(value: LongArray): LongArray { 76 | return AdditionalMatchers.aryEq(value) ?: createInstance() 77 | } 78 | 79 | /** 80 | * int array argument that is equal to the given array, i.e. it has to have the same length, and 81 | * each element has to be equal. 82 | */ 83 | fun aryEq(value: IntArray): IntArray { 84 | return AdditionalMatchers.aryEq(value) ?: createInstance() 85 | } 86 | 87 | /** 88 | * float array argument that is equal to the given array, i.e. it has to have the same length, and 89 | * each element has to be equal. 90 | */ 91 | fun aryEq(value: FloatArray): FloatArray { 92 | return AdditionalMatchers.aryEq(value) ?: createInstance() 93 | } 94 | 95 | /** 96 | * double array argument that is equal to the given array, i.e. it has to have the same length, and 97 | * each element has to be equal. 98 | */ 99 | fun aryEq(value: DoubleArray): DoubleArray { 100 | return AdditionalMatchers.aryEq(value) ?: createInstance() 101 | } 102 | 103 | /** 104 | * char array argument that is equal to the given array, i.e. it has to have the same length, and 105 | * each element has to be equal. 106 | */ 107 | fun aryEq(value: CharArray): CharArray { 108 | return AdditionalMatchers.aryEq(value) ?: createInstance() 109 | } 110 | 111 | /** 112 | * byte array argument that is equal to the given array, i.e. it has to have the same length, and 113 | * each element has to be equal. 114 | */ 115 | fun aryEq(value: ByteArray): ByteArray { 116 | return AdditionalMatchers.aryEq(value) ?: createInstance() 117 | } 118 | 119 | /** 120 | * boolean array argument that is equal to the given array, i.e. it has to have the same length, and 121 | * each element has to be equal. 122 | */ 123 | fun aryEq(value: BooleanArray): BooleanArray { 124 | return AdditionalMatchers.aryEq(value) ?: createInstance() 125 | } 126 | 127 | /** String argument that contains a substring that matches the given regular expression. */ 128 | fun find(regex: Regex): String { 129 | return AdditionalMatchers.find(regex.pattern) ?: "" 130 | } 131 | 132 | /** argument that matches both given argument matchers. */ 133 | inline fun and(left: T, right: T): T { 134 | return AdditionalMatchers.and(left, right) ?: createInstance() 135 | } 136 | 137 | /** argument that matches both given argument matchers. */ 138 | inline fun or(left: T, right: T): T { 139 | return AdditionalMatchers.or(left, right) ?: createInstance() 140 | } 141 | 142 | /** argument that does not match the given argument matcher. */ 143 | inline fun not(matcher: T): T { 144 | return AdditionalMatchers.not(matcher) ?: createInstance() 145 | } 146 | -------------------------------------------------------------------------------- /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 | /** 194 | * The *only* captured value of the argument, 195 | * or throws an exception if no value or more than one value was captured. 196 | */ 197 | val singleValue: T 198 | get() = captor.singleValue 199 | 200 | val allValues: List 201 | get() = captor.allValues 202 | 203 | @Suppress("UNCHECKED_CAST") 204 | fun capture(): T { 205 | // Special handling for arrays to make it work for varargs 206 | // In Kotlin we want have to capture vararg like this `verify(m).methodName(*captor.capture())` to make the types work 207 | // If we return null for array types, the spread `*` operator will fail with NPE 208 | // If we return empty array, it will fail in MatchersBinder.validateMatchers 209 | // In Java, `captor.capture` returns null and so the method is called with `[null]` 210 | // In Kotlin, we have to create `[null]` explicitly. 211 | // This code-path is applied for non-vararg array arguments as well, but it seems to work fine. 212 | return captor.capture() ?: if (tClass.java.isArray) { 213 | singleElementArray() 214 | } else { 215 | createInstance(tClass) 216 | } as T 217 | } 218 | 219 | private fun singleElementArray(): Any? = Array.newInstance(tClass.java.componentType, 1) 220 | } 221 | 222 | val ArgumentCaptor.firstValue: T 223 | get() = allValues[0] 224 | 225 | val ArgumentCaptor.secondValue: T 226 | get() = allValues[1] 227 | 228 | val ArgumentCaptor.thirdValue: T 229 | get() = allValues[2] 230 | 231 | val ArgumentCaptor.lastValue: T 232 | get() = allValues.last() 233 | 234 | val ArgumentCaptor.singleValue: T 235 | get() = allValues.single() 236 | -------------------------------------------------------------------------------- /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/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/KInvocationOnMock.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.invocation.InvocationOnMock 29 | 30 | class KInvocationOnMock( 31 | private val invocationOnMock: InvocationOnMock 32 | ) : InvocationOnMock by invocationOnMock { 33 | 34 | operator fun component1(): T = invocationOnMock.getArgument(0) 35 | operator fun component2(): T = invocationOnMock.getArgument(1) 36 | operator fun component3(): T = invocationOnMock.getArgument(2) 37 | operator fun component4(): T = invocationOnMock.getArgument(3) 38 | operator fun component5(): T = invocationOnMock.getArgument(4) 39 | } 40 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | if(T::class.isValue) 46 | return anyValueClass() 47 | 48 | return ArgumentMatchers.any(T::class.java) ?: createInstance() 49 | } 50 | 51 | /** Matches anything, including nulls. */ 52 | inline fun anyOrNull(): T { 53 | return ArgumentMatchers.any() ?: createInstance() 54 | } 55 | 56 | /** Matches any vararg object, including nulls. */ 57 | inline fun anyVararg(): T { 58 | return anyVararg(T::class) 59 | } 60 | 61 | fun anyVararg(clazz: KClass): T { 62 | return ArgumentMatchers.argThat(VarargMatcher(clazz.java)) ?: createInstance(clazz) 63 | } 64 | 65 | private class VarargMatcher(private val clazz: Class) : ArgumentMatcher { 66 | override fun matches(t: T): Boolean = true 67 | 68 | // In Java >= 12 you can do clazz.arrayClass() 69 | override fun type(): Class<*> = java.lang.reflect.Array.newInstance(clazz, 0).javaClass 70 | } 71 | 72 | /** Matches any array of type T. */ 73 | inline fun anyArray(): Array { 74 | return ArgumentMatchers.any(Array::class.java) ?: arrayOf() 75 | } 76 | 77 | /** Matches any Kotlin value class with the same boxed type by taking its boxed type. */ 78 | inline fun anyValueClass(): T { 79 | require(T::class.isValue) { 80 | "${T::class.qualifiedName} is not a value class." 81 | } 82 | 83 | val boxImpls = T::class.java.declaredMethods.filter { it.name == "box-impl" && it.parameterCount == 1 } 84 | require(boxImpls.size == 1) // Sanity check 85 | 86 | val boxImpl = boxImpls.first() 87 | val boxedType = boxImpl.parameters[0].type 88 | 89 | return boxImpl.invoke(null, ArgumentMatchers.any(boxedType)) as T 90 | } 91 | 92 | /** 93 | * Creates a custom argument matcher. 94 | * `null` values will never evaluate to `true`. 95 | * 96 | * @param predicate An extension function on [T] that returns `true` when a [T] matches the predicate. 97 | */ 98 | inline fun argThat(noinline predicate: T.() -> Boolean): T { 99 | return ArgumentMatchers.argThat { arg: T? -> arg?.predicate() ?: false } ?: createInstance( 100 | T::class 101 | ) 102 | } 103 | 104 | /** 105 | * Registers a custom ArgumentMatcher. The original Mockito function registers the matcher and returns null, 106 | * here the required type is returned. 107 | * 108 | * @param matcher The ArgumentMatcher on [T] to be registered. 109 | */ 110 | inline fun argThat(matcher: ArgumentMatcher): T { 111 | return ArgumentMatchers.argThat(matcher) ?: createInstance() 112 | } 113 | 114 | /** 115 | * Alias for [argThat]. 116 | * 117 | * Creates a custom argument matcher. 118 | * `null` values will never evaluate to `true`. 119 | * 120 | * @param predicate An extension function on [T] that returns `true` when a [T] matches the predicate. 121 | */ 122 | inline fun argForWhich(noinline predicate: T.() -> Boolean): T { 123 | return argThat(predicate) 124 | } 125 | 126 | /** 127 | * Creates a custom argument matcher. 128 | * `null` values will never evaluate to `true`. 129 | * 130 | * @param predicate A function that returns `true` when given [T] matches the predicate. 131 | */ 132 | inline fun argWhere(noinline predicate: (T) -> Boolean): T { 133 | return argThat(predicate) 134 | } 135 | 136 | /** 137 | * Argument that implements the given class. 138 | */ 139 | inline fun isA(): T { 140 | return ArgumentMatchers.isA(T::class.java) ?: createInstance() 141 | } 142 | 143 | /** 144 | * `null` argument. 145 | */ 146 | fun isNull(): T? = ArgumentMatchers.isNull() 147 | 148 | /** 149 | * Not `null` argument. 150 | */ 151 | fun isNotNull(): T? { 152 | return ArgumentMatchers.isNotNull() 153 | } 154 | 155 | /** 156 | * Not `null` argument. 157 | */ 158 | fun notNull(): T? { 159 | return ArgumentMatchers.notNull() 160 | } 161 | 162 | /** 163 | * Object argument that is reflection-equal to the given value with support for excluding 164 | * selected fields from a class. 165 | */ 166 | inline fun refEq(value: T, vararg excludeFields: String): T { 167 | return ArgumentMatchers.refEq(value, *excludeFields) ?: createInstance() 168 | } 169 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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/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.kotlin.internal.KAnswer 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: (KInvocationOnMock) -> T?): OngoingStubbing { 136 | return thenAnswer(KAnswer(answer)) 137 | } 138 | 139 | infix fun OngoingStubbing.doSuspendableAnswer(answer: suspend (KInvocationOnMock) -> T?): OngoingStubbing { 140 | return thenAnswer(SuspendableAnswer(answer)) 141 | } 142 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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.kotlin.internal.SuspendableAnswer 32 | import org.mockito.stubbing.OngoingStubbing 33 | import org.mockito.stubbing.Stubber 34 | import kotlin.reflect.KClass 35 | 36 | fun doAnswer(answer: (InvocationOnMock) -> T?): Stubber { 37 | return Mockito.doAnswer { answer(it) }!! 38 | } 39 | 40 | fun doSuspendableAnswer(answer: suspend (KInvocationOnMock) -> T?): Stubber { 41 | return Mockito.doAnswer(SuspendableAnswer(answer)) 42 | } 43 | 44 | fun doCallRealMethod(): Stubber { 45 | return Mockito.doCallRealMethod()!! 46 | } 47 | 48 | fun doNothing(): Stubber { 49 | return Mockito.doNothing()!! 50 | } 51 | 52 | fun doReturn(value: Any?): Stubber { 53 | return Mockito.doReturn(value)!! 54 | } 55 | 56 | fun doReturn(toBeReturned: Any?, vararg toBeReturnedNext: Any?): Stubber { 57 | return Mockito.doReturn( 58 | toBeReturned, 59 | *toBeReturnedNext 60 | )!! 61 | } 62 | 63 | fun doThrow(toBeThrown: KClass): Stubber { 64 | return Mockito.doThrow(toBeThrown.java)!! 65 | } 66 | 67 | fun doThrow(vararg toBeThrown: Throwable): Stubber { 68 | return Mockito.doThrow(*toBeThrown)!! 69 | } 70 | 71 | fun Stubber.whenever(mock: T) = `when`(mock) 72 | 73 | /** 74 | * Alias for when with suspending function 75 | * 76 | * Warning: Only one method call can be stubbed in the function. 77 | * Subsequent method calls are ignored! 78 | */ 79 | fun Stubber.wheneverBlocking(mock: T, f: suspend T.() -> Unit) { 80 | val m = whenever(mock) 81 | runBlocking { m.f() } 82 | } 83 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /mockito-kotlin/src/main/kotlin/org/mockito/kotlin/internal/KAnswer.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.invocation.InvocationOnMock 29 | import org.mockito.kotlin.KInvocationOnMock 30 | import org.mockito.stubbing.Answer 31 | 32 | /** 33 | * This class wraps destructuring lambda into [Answer] 34 | */ 35 | @Suppress("UNCHECKED_CAST") 36 | internal class KAnswer( 37 | private val body: (KInvocationOnMock) -> T? 38 | ) : Answer { 39 | override fun answer(invocation: InvocationOnMock): T { 40 | return body(KInvocationOnMock(invocation)) as T 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /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/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.kotlin.KInvocationOnMock 31 | import org.mockito.stubbing.Answer 32 | import kotlin.coroutines.Continuation 33 | import kotlin.coroutines.intrinsics.startCoroutineUninterceptedOrReturn 34 | 35 | /** 36 | * This class properly wraps suspendable lambda into [Answer] 37 | */ 38 | @Suppress("UNCHECKED_CAST") 39 | internal class SuspendableAnswer( 40 | private val body: suspend (KInvocationOnMock) -> T? 41 | ) : Answer { 42 | override fun answer(invocation: InvocationOnMock?): T { 43 | //all suspend functions/lambdas has Continuation as the last argument. 44 | //InvocationOnMock does not see last argument 45 | val rawInvocation = invocation as InterceptedInvocation 46 | val continuation = rawInvocation.rawArguments.last() as Continuation 47 | 48 | // https://youtrack.jetbrains.com/issue/KT-33766#focus=Comments-27-3707299.0-0 49 | return body.startCoroutineUninterceptedOrReturn(KInvocationOnMock(invocation), continuation) as T 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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.* 7 | import kotlinx.coroutines.channels.actor 8 | import org.junit.Assert.assertEquals 9 | import org.junit.Assert.assertThrows 10 | import org.junit.Test 11 | import org.mockito.InOrder 12 | import org.mockito.kotlin.* 13 | import java.util.* 14 | 15 | class CoroutinesTest { 16 | 17 | @Test 18 | fun stubbingSuspending() { 19 | /* Given */ 20 | val m = mock { 21 | onBlocking { suspending() } doReturn 42 22 | } 23 | 24 | /* When */ 25 | val result = runBlocking { m.suspending() } 26 | 27 | /* Then */ 28 | expect(result).toBe(42) 29 | } 30 | 31 | @Test 32 | fun stubbingSuspending_usingSuspendingFunction() { 33 | /* Given */ 34 | val m = mock { 35 | onBlocking { suspending() } doReturn runBlocking { SomeClass().result(42) } 36 | } 37 | 38 | /* When */ 39 | val result = runBlocking { m.suspending() } 40 | 41 | /* Then */ 42 | expect(result).toBe(42) 43 | } 44 | 45 | @Test 46 | fun stubbingSuspending_runBlocking() = runBlocking { 47 | /* Given */ 48 | val m = mock { 49 | onBlocking { suspending() } doReturn 42 50 | } 51 | 52 | /* When */ 53 | val result = m.suspending() 54 | 55 | /* Then */ 56 | expect(result).toBe(42) 57 | } 58 | 59 | @Test 60 | fun stubbingSuspending_wheneverBlocking() { 61 | /* Given */ 62 | val m: SomeInterface = mock() 63 | wheneverBlocking { m.suspending() } 64 | .doReturn(42) 65 | 66 | /* When */ 67 | val result = runBlocking { m.suspending() } 68 | 69 | /* Then */ 70 | expect(result).toBe(42) 71 | } 72 | 73 | @Test 74 | fun stubbingSuspending_doReturn() { 75 | /* Given */ 76 | val m = spy(SomeClass()) 77 | doReturn(10) 78 | .wheneverBlocking(m) { 79 | delaying() 80 | } 81 | 82 | /* When */ 83 | val result = runBlocking { m.delaying() } 84 | 85 | /* Then */ 86 | expect(result).toBe(10) 87 | } 88 | 89 | @Test 90 | fun stubbingNonSuspending() { 91 | /* Given */ 92 | val m = mock { 93 | onBlocking { nonsuspending() } doReturn 42 94 | } 95 | 96 | /* When */ 97 | val result = m.nonsuspending() 98 | 99 | /* Then */ 100 | expect(result).toBe(42) 101 | } 102 | 103 | @Test 104 | fun stubbingNonSuspending_runBlocking() = runBlocking { 105 | /* Given */ 106 | val m = mock { 107 | onBlocking { nonsuspending() } doReturn 42 108 | } 109 | 110 | /* When */ 111 | val result = m.nonsuspending() 112 | 113 | /* Then */ 114 | expect(result).toBe(42) 115 | } 116 | 117 | @Test 118 | fun delayingResult() { 119 | /* Given */ 120 | val m = SomeClass() 121 | 122 | /* When */ 123 | val result = runBlocking { m.delaying() } 124 | 125 | /* Then */ 126 | expect(result).toBe(42) 127 | } 128 | 129 | @Test 130 | fun delayingResult_runBlocking() = runBlocking { 131 | /* Given */ 132 | val m = SomeClass() 133 | 134 | /* When */ 135 | val result = m.delaying() 136 | 137 | /* Then */ 138 | expect(result).toBe(42) 139 | } 140 | 141 | @Test 142 | fun verifySuspendFunctionCalled() { 143 | /* Given */ 144 | val m = mock() 145 | 146 | /* When */ 147 | runBlocking { m.suspending() } 148 | 149 | /* Then */ 150 | runBlocking { verify(m).suspending() } 151 | } 152 | 153 | @Test 154 | fun verifySuspendFunctionCalled_runBlocking() = runBlocking { 155 | val m = mock() 156 | 157 | m.suspending() 158 | 159 | verify(m).suspending() 160 | } 161 | 162 | @Test 163 | fun verifySuspendFunctionCalled_verifyBlocking() { 164 | val m = mock() 165 | 166 | runBlocking { m.suspending() } 167 | 168 | verifyBlocking(m) { suspending() } 169 | } 170 | 171 | @Test 172 | fun verifyAtLeastOnceSuspendFunctionCalled_verifyBlocking() { 173 | val m = mock() 174 | 175 | runBlocking { m.suspending() } 176 | runBlocking { m.suspending() } 177 | 178 | verifyBlocking(m, atLeastOnce()) { suspending() } 179 | } 180 | 181 | @Test 182 | fun verifySuspendMethod() = runBlocking { 183 | val testSubject: SomeInterface = mock() 184 | 185 | testSubject.suspending() 186 | 187 | inOrder(testSubject) { 188 | verify(testSubject).suspending() 189 | } 190 | } 191 | 192 | @Test 193 | fun answerWithSuspendFunction() = runBlocking { 194 | val fixture: SomeInterface = mock() 195 | 196 | whenever(fixture.suspendingWithArg(any())).doSuspendableAnswer { 197 | withContext(Dispatchers.Default) { it.getArgument(0) } 198 | } 199 | 200 | assertEquals(5, fixture.suspendingWithArg(5)) 201 | } 202 | 203 | @Test 204 | fun inplaceAnswerWithSuspendFunction() = runBlocking { 205 | val fixture: SomeInterface = mock { 206 | onBlocking { suspendingWithArg(any()) } doSuspendableAnswer { 207 | withContext(Dispatchers.Default) { it.getArgument(0) } 208 | } 209 | } 210 | 211 | assertEquals(5, fixture.suspendingWithArg(5)) 212 | } 213 | 214 | @Test 215 | fun callFromSuspendFunction() = runBlocking { 216 | val fixture: SomeInterface = mock() 217 | 218 | whenever(fixture.suspendingWithArg(any())).doSuspendableAnswer { 219 | withContext(Dispatchers.Default) { it.getArgument(0) } 220 | } 221 | 222 | val result = async { 223 | val answer = fixture.suspendingWithArg(5) 224 | 225 | Result.success(answer) 226 | } 227 | 228 | assertEquals(5, result.await().getOrThrow()) 229 | } 230 | 231 | @Test 232 | fun callFromActor() = runBlocking { 233 | val fixture: SomeInterface = mock() 234 | 235 | whenever(fixture.suspendingWithArg(any())).doSuspendableAnswer { 236 | withContext(Dispatchers.Default) { it.getArgument(0) } 237 | } 238 | 239 | val actor = actor> { 240 | for (element in channel) { 241 | fixture.suspendingWithArg(element.get()) 242 | } 243 | } 244 | 245 | actor.send(Optional.of(10)) 246 | actor.close() 247 | 248 | verify(fixture).suspendingWithArg(10) 249 | 250 | Unit 251 | } 252 | 253 | @Test 254 | fun answerWithSuspendFunctionWithoutArgs() = runBlocking { 255 | val fixture: SomeInterface = mock() 256 | 257 | whenever(fixture.suspending()).doSuspendableAnswer { 258 | withContext(Dispatchers.Default) { 42 } 259 | } 260 | 261 | assertEquals(42, fixture.suspending()) 262 | } 263 | 264 | @Test 265 | fun answerWithSuspendFunctionWithDestructuredArgs() = runBlocking { 266 | val fixture: SomeInterface = mock() 267 | 268 | whenever(fixture.suspendingWithArg(any())).doSuspendableAnswer { (i: Int) -> 269 | withContext(Dispatchers.Default) { i } 270 | } 271 | 272 | assertEquals(5, fixture.suspendingWithArg(5)) 273 | } 274 | 275 | @Test 276 | fun willAnswerWithControlledSuspend() = runBlocking { 277 | val fixture: SomeInterface = mock() 278 | 279 | val job = Job() 280 | 281 | whenever(fixture.suspending()).doSuspendableAnswer { 282 | job.join() 283 | 5 284 | } 285 | 286 | val asyncTask = async { 287 | fixture.suspending() 288 | } 289 | 290 | job.complete() 291 | 292 | withTimeout(100) { 293 | assertEquals(5, asyncTask.await()) 294 | } 295 | } 296 | 297 | @Test 298 | fun stubberAnswerWithSuspendFunction() = runBlocking { 299 | val fixture: SomeInterface = mock() 300 | 301 | doSuspendableAnswer { 302 | withContext(Dispatchers.Default) { it.getArgument(0) } 303 | }.whenever(fixture).suspendingWithArg(any()) 304 | 305 | assertEquals(5, fixture.suspendingWithArg(5)) 306 | } 307 | 308 | @Test 309 | fun stubberCallFromSuspendFunction() = runBlocking { 310 | val fixture: SomeInterface = mock() 311 | 312 | doSuspendableAnswer { 313 | withContext(Dispatchers.Default) { it.getArgument(0) } 314 | }.whenever(fixture).suspendingWithArg(any()) 315 | 316 | val result = async { 317 | val answer = fixture.suspendingWithArg(5) 318 | 319 | Result.success(answer) 320 | } 321 | 322 | assertEquals(5, result.await().getOrThrow()) 323 | } 324 | 325 | @Test 326 | fun stubberCallFromActor() = runBlocking { 327 | val fixture: SomeInterface = mock() 328 | 329 | doSuspendableAnswer { 330 | withContext(Dispatchers.Default) { it.getArgument(0) } 331 | }.whenever(fixture).suspendingWithArg(any()) 332 | 333 | val actor = actor> { 334 | for (element in channel) { 335 | fixture.suspendingWithArg(element.get()) 336 | } 337 | } 338 | 339 | actor.send(Optional.of(10)) 340 | actor.close() 341 | 342 | verify(fixture).suspendingWithArg(10) 343 | 344 | Unit 345 | } 346 | 347 | @Test 348 | fun stubberAnswerWithSuspendFunctionWithoutArgs() = runBlocking { 349 | val fixture: SomeInterface = mock() 350 | 351 | doSuspendableAnswer { 352 | withContext(Dispatchers.Default) { 42 } 353 | }.whenever(fixture).suspending() 354 | 355 | assertEquals(42, fixture.suspending()) 356 | } 357 | 358 | @Test 359 | fun stubberAnswerWithSuspendFunctionWithDestructuredArgs() = runBlocking { 360 | val fixture: SomeInterface = mock() 361 | 362 | doSuspendableAnswer { (i: Int) -> 363 | withContext(Dispatchers.Default) { i } 364 | }.whenever(fixture).suspendingWithArg(any()) 365 | 366 | assertEquals(5, fixture.suspendingWithArg(5)) 367 | } 368 | 369 | @Test 370 | fun stubberWillAnswerWithControlledSuspend() = runBlocking { 371 | val fixture: SomeInterface = mock() 372 | 373 | val job = Job() 374 | 375 | doSuspendableAnswer { 376 | job.join() 377 | 5 378 | }.whenever(fixture).suspending() 379 | 380 | val asyncTask = async { 381 | fixture.suspending() 382 | } 383 | 384 | job.complete() 385 | 386 | withTimeout(100) { 387 | assertEquals(5, asyncTask.await()) 388 | } 389 | } 390 | 391 | @Test 392 | fun inOrderRemainsCompatible() { 393 | /* Given */ 394 | val fixture: SomeInterface = mock() 395 | 396 | /* When */ 397 | val inOrder = inOrder(fixture) 398 | 399 | /* Then */ 400 | expect(inOrder).toBeInstanceOf() 401 | } 402 | 403 | @Test 404 | fun inOrderSuspendingCalls() { 405 | /* Given */ 406 | val fixtureOne: SomeInterface = mock() 407 | val fixtureTwo: SomeInterface = mock() 408 | 409 | /* When */ 410 | runBlocking { 411 | fixtureOne.suspending() 412 | fixtureTwo.suspending() 413 | } 414 | 415 | /* Then */ 416 | val inOrder = inOrder(fixtureOne, fixtureTwo) 417 | inOrder.verifyBlocking(fixtureOne) { suspending() } 418 | inOrder.verifyBlocking(fixtureTwo) { suspending() } 419 | } 420 | 421 | @Test 422 | fun inOrderSuspendingCallsFailure() { 423 | /* Given */ 424 | val fixtureOne: SomeInterface = mock() 425 | val fixtureTwo: SomeInterface = mock() 426 | 427 | /* When */ 428 | runBlocking { 429 | fixtureOne.suspending() 430 | fixtureTwo.suspending() 431 | } 432 | 433 | /* Then */ 434 | val inOrder = inOrder(fixtureOne, fixtureTwo) 435 | inOrder.verifyBlocking(fixtureTwo) { suspending() } 436 | assertThrows(AssertionError::class.java) { 437 | inOrder.verifyBlocking(fixtureOne) { suspending() } 438 | } 439 | } 440 | 441 | @Test 442 | fun inOrderBlockSuspendingCalls() { 443 | /* Given */ 444 | val fixtureOne: SomeInterface = mock() 445 | val fixtureTwo: SomeInterface = mock() 446 | 447 | /* When */ 448 | runBlocking { 449 | fixtureOne.suspending() 450 | fixtureTwo.suspending() 451 | } 452 | 453 | /* Then */ 454 | inOrder(fixtureOne, fixtureTwo) { 455 | verifyBlocking(fixtureOne) { suspending() } 456 | verifyBlocking(fixtureTwo) { suspending() } 457 | } 458 | } 459 | 460 | @Test 461 | fun inOrderBlockSuspendingCallsFailure() { 462 | /* Given */ 463 | val fixtureOne: SomeInterface = mock() 464 | val fixtureTwo: SomeInterface = mock() 465 | 466 | /* When */ 467 | runBlocking { 468 | fixtureOne.suspending() 469 | fixtureTwo.suspending() 470 | } 471 | 472 | /* Then */ 473 | inOrder(fixtureOne, fixtureTwo) { 474 | verifyBlocking(fixtureTwo) { suspending() } 475 | assertThrows(AssertionError::class.java) { 476 | verifyBlocking(fixtureOne) { suspending() } 477 | } 478 | } 479 | } 480 | 481 | @Test 482 | fun inOrderOnObjectSuspendingCalls() { 483 | /* Given */ 484 | val fixture: SomeInterface = mock() 485 | 486 | /* When */ 487 | runBlocking { 488 | fixture.suspendingWithArg(1) 489 | fixture.suspendingWithArg(2) 490 | } 491 | 492 | /* Then */ 493 | fixture.inOrder { 494 | verifyBlocking { suspendingWithArg(1) } 495 | verifyBlocking { suspendingWithArg(2) } 496 | } 497 | } 498 | 499 | @Test 500 | fun inOrderOnObjectSuspendingCallsFailure() { 501 | /* Given */ 502 | val fixture: SomeInterface = mock() 503 | 504 | /* When */ 505 | runBlocking { 506 | fixture.suspendingWithArg(1) 507 | fixture.suspendingWithArg(2) 508 | } 509 | 510 | /* Then */ 511 | fixture.inOrder { 512 | verifyBlocking { suspendingWithArg(2) } 513 | assertThrows(AssertionError::class.java) { 514 | verifyBlocking { suspendingWithArg(1) } 515 | } 516 | } 517 | } 518 | } 519 | 520 | interface SomeInterface { 521 | 522 | suspend fun suspending(): Int 523 | suspend fun suspendingWithArg(arg: Int): Int 524 | fun nonsuspending(): Int 525 | } 526 | 527 | open class SomeClass { 528 | 529 | suspend fun result(r: Int) = withContext(Dispatchers.Default) { r } 530 | 531 | open suspend fun delaying() = withContext(Dispatchers.Default) { 532 | delay(100) 533 | 42 534 | } 535 | } 536 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /ops/org.mockito.plugins.MockMaker: -------------------------------------------------------------------------------- 1 | mock-maker-inline -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'mockito-kotlin-root' 2 | 3 | include 'mockito-kotlin' 4 | includeBuild 'tests' 5 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.9.0-RC" 23 | } 24 | 25 | tasks.withType(KotlinCompile).configureEach { 26 | compilerOptions { 27 | jvmTarget.set(JvmTarget.JVM_11) 28 | targetCompatibility = "11" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /tests/settings.gradle: -------------------------------------------------------------------------------- 1 | includeBuild '..' 2 | -------------------------------------------------------------------------------- /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 testAryEqBoolean() { 57 | mock().apply { 58 | booleanArray(booleanArrayOf(true, false, true)) 59 | verify(this).booleanArray(aryEq(booleanArrayOf(true, false, true))) 60 | verify(this, never()).booleanArray(aryEq(booleanArrayOf(true, false))) 61 | } 62 | } 63 | 64 | @Test 65 | fun testAryEqByte() { 66 | mock().apply { 67 | byteArray(byteArrayOf(1, 2, 3)) 68 | verify(this).byteArray(aryEq(byteArrayOf(1, 2, 3))) 69 | verify(this, never()).byteArray(aryEq(byteArrayOf(1, 2))) 70 | } 71 | } 72 | 73 | @Test 74 | fun testAryEqShort() { 75 | mock().apply { 76 | shortArray(shortArrayOf(1, 2, 3)) 77 | verify(this).shortArray(aryEq(shortArrayOf(1, 2, 3))) 78 | verify(this, never()).shortArray(aryEq(shortArrayOf(1, 2))) 79 | } 80 | } 81 | 82 | @Test 83 | fun testAryEqInt() { 84 | mock().apply { 85 | intArray(intArrayOf(1, 2, 3)) 86 | verify(this).intArray(aryEq(intArrayOf(1, 2, 3))) 87 | verify(this, never()).intArray(aryEq(intArrayOf(1, 2))) 88 | } 89 | } 90 | 91 | @Test 92 | fun testAryEqLong() { 93 | mock().apply { 94 | longArray(longArrayOf(1, 2, 3)) 95 | verify(this).longArray(aryEq(longArrayOf(1, 2, 3))) 96 | verify(this, never()).longArray(aryEq(longArrayOf(1, 2))) 97 | } 98 | } 99 | 100 | @Test 101 | fun testAryEqChar() { 102 | mock().apply { 103 | charArray(charArrayOf('1', '2', '3')) 104 | verify(this).charArray(aryEq(charArrayOf('1', '2', '3'))) 105 | verify(this, never()).charArray(aryEq(charArrayOf('1', '2'))) 106 | } 107 | } 108 | 109 | @Test 110 | fun testAryEqFloat() { 111 | mock().apply { 112 | floatArray(floatArrayOf(1f, 2f, 3.4f)) 113 | verify(this).floatArray(aryEq(floatArrayOf(1f, 2f, 3.4f))) 114 | verify(this, never()).floatArray(aryEq(floatArrayOf(1f, 2f))) 115 | } 116 | } 117 | 118 | @Test 119 | fun testAryEqDouble() { 120 | mock().apply { 121 | doubleArray(doubleArrayOf(1.0, 2.0, 3.4)) 122 | verify(this).doubleArray(aryEq(doubleArrayOf(1.0, 2.0, 3.4))) 123 | verify(this, never()).doubleArray(aryEq(doubleArrayOf(1.0, 2.0))) 124 | } 125 | } 126 | 127 | @Test 128 | fun testAryEq() { 129 | mock().apply { 130 | stringArray(arrayOf("Hello", "there")) 131 | verify(this).stringArray(aryEq(arrayOf("Hello", "there"))) 132 | verify(this, never()).stringArray(aryEq(arrayOf("Hello"))) 133 | } 134 | } 135 | 136 | @Test 137 | fun testFind() { 138 | mock().apply { 139 | string("Hello") 140 | verify(this).string(find("l+o$".toRegex())) 141 | verify(this, never()).string(find("l$".toRegex())) 142 | } 143 | } 144 | 145 | @Test 146 | fun testAnd() { 147 | mock().apply { 148 | int(5) 149 | verify(this).int(and(geq(4), leq(6))) 150 | verify(this, never()).int(and(geq(4), leq(4))) 151 | } 152 | } 153 | 154 | @Test 155 | fun testOr() { 156 | mock().apply { 157 | int(5) 158 | verify(this).int(and(gt(4), lt(6))) 159 | verify(this, never()).int(and(gt(4), lt(4))) 160 | } 161 | } 162 | 163 | @Test 164 | fun testNot() { 165 | mock().apply { 166 | int(5) 167 | verify(this).int(not(eq(4))) 168 | verify(this, never()).int(not(eq(5))) 169 | } 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /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.ArgumentCaptor 7 | import org.mockito.ArgumentMatchers 8 | import org.mockito.ArgumentMatchers.anyLong 9 | import org.mockito.kotlin.* 10 | import java.util.* 11 | 12 | class ArgumentCaptorTest : TestBase() { 13 | 14 | @Test 15 | fun argumentCaptor_withSingleValue() { 16 | /* Given */ 17 | val date: Date = mock() 18 | 19 | /* When */ 20 | date.time = 5L 21 | 22 | /* Then */ 23 | val captor = argumentCaptor() 24 | verify(date).time = captor.capture() 25 | expect(captor.lastValue).toBe(5L) 26 | } 27 | 28 | @Test 29 | fun argumentCaptor_destructuring2() { 30 | /* Given */ 31 | val date: Date = mock() 32 | 33 | /* When */ 34 | date.time = 5L 35 | 36 | /* Then */ 37 | val (captor1, captor2) = argumentCaptor() 38 | verify(date).time = captor1.capture() 39 | verify(date).time = captor2.capture() 40 | expect(captor1.lastValue).toBe(5L) 41 | expect(captor2.lastValue).toBe(5L) 42 | } 43 | 44 | @Test 45 | fun argumentCaptor_destructuring3() { 46 | /* Given */ 47 | val date: Date = mock() 48 | 49 | /* When */ 50 | date.time = 5L 51 | 52 | /* Then */ 53 | val (captor1, captor2, captor3) = argumentCaptor() 54 | val verifyCaptor: KArgumentCaptor.() -> Unit = { 55 | verify(date).time = capture() 56 | expect(lastValue).toBe(5L) 57 | } 58 | captor1.apply(verifyCaptor) 59 | captor2.apply(verifyCaptor) 60 | captor3.apply(verifyCaptor) 61 | } 62 | 63 | @Test 64 | fun argumentCaptor_destructuring4() { 65 | /* Given */ 66 | val date: Date = mock() 67 | 68 | /* When */ 69 | date.time = 5L 70 | 71 | /* Then */ 72 | val (captor1, captor2, captor3, captor4) = argumentCaptor() 73 | val verifyCaptor: KArgumentCaptor.() -> Unit = { 74 | verify(date).time = capture() 75 | expect(lastValue).toBe(5L) 76 | } 77 | captor1.apply(verifyCaptor) 78 | captor2.apply(verifyCaptor) 79 | captor3.apply(verifyCaptor) 80 | captor4.apply(verifyCaptor) 81 | } 82 | 83 | @Test 84 | fun argumentCaptor_destructuring5() { 85 | /* Given */ 86 | val date: Date = mock() 87 | 88 | /* When */ 89 | date.time = 5L 90 | 91 | /* Then */ 92 | val (captor1, captor2, captor3, captor4, captor5) = argumentCaptor() 93 | val verifyCaptor: KArgumentCaptor.() -> Unit = { 94 | verify(date).time = capture() 95 | expect(lastValue).toBe(5L) 96 | } 97 | captor1.apply(verifyCaptor) 98 | captor2.apply(verifyCaptor) 99 | captor3.apply(verifyCaptor) 100 | captor4.apply(verifyCaptor) 101 | captor5.apply(verifyCaptor) 102 | } 103 | 104 | @Test 105 | fun argumentCaptor_withNullValue_usingNonNullable() { 106 | /* Given */ 107 | val m: Methods = mock() 108 | 109 | /* When */ 110 | m.nullableString(null) 111 | 112 | /* Then */ 113 | val captor = argumentCaptor() 114 | verify(m).nullableString(captor.capture()) 115 | expect(captor.lastValue).toBeNull() 116 | } 117 | 118 | @Test 119 | fun argumentCaptor_withNullValue_usingNullable() { 120 | /* Given */ 121 | val m: Methods = mock() 122 | 123 | /* When */ 124 | m.nullableString(null) 125 | 126 | /* Then */ 127 | val captor = nullableArgumentCaptor() 128 | verify(m).nullableString(captor.capture()) 129 | expect(captor.lastValue).toBeNull() 130 | } 131 | 132 | @Test 133 | fun argumentCaptor_singleValue() { 134 | /* Given */ 135 | val date: Date = mock() 136 | 137 | /* When */ 138 | date.time = 5L 139 | 140 | /* Then */ 141 | val captor = argumentCaptor() 142 | verify(date).time = captor.capture() 143 | expect(captor.singleValue).toBe(5L) 144 | } 145 | 146 | @Test(expected = IllegalArgumentException::class) 147 | fun argumentCaptor_singleValue_properlyFails() { 148 | /* Given */ 149 | val date: Date = mock() 150 | val captor = argumentCaptor() 151 | doNothing().whenever(date).time = captor.capture() 152 | 153 | /* When */ 154 | date.time = 5L 155 | date.time = 7L 156 | 157 | /* Then */ 158 | expect(captor.singleValue).toBe(5) 159 | } 160 | 161 | @Test 162 | fun argumentCaptor_multipleValues() { 163 | /* Given */ 164 | val date: Date = mock() 165 | 166 | /* When */ 167 | date.time = 5L 168 | date.time = 7L 169 | 170 | /* Then */ 171 | val captor = argumentCaptor() 172 | verify(date, times(2)).time = captor.capture() 173 | expect(captor.allValues).toBe(listOf(5, 7)) 174 | } 175 | 176 | @Test 177 | fun argumentCaptor_multipleValuesIncludingNull() { 178 | /* Given */ 179 | val m: Methods = mock() 180 | 181 | /* When */ 182 | m.nullableString("test") 183 | m.nullableString(null) 184 | 185 | /* Then */ 186 | val captor = nullableArgumentCaptor() 187 | verify(m, times(2)).nullableString(captor.capture()) 188 | expect(captor.allValues).toBe(listOf("test", null)) 189 | } 190 | 191 | @Test 192 | fun argumentCaptor_callProperties() { 193 | /* Given */ 194 | val m: Methods = mock() 195 | 196 | /* When */ 197 | m.int(1) 198 | m.int(2) 199 | m.int(3) 200 | m.int(4) 201 | m.int(5) 202 | 203 | /* Then */ 204 | argumentCaptor().apply { 205 | verify(m, times(5)).int(capture()) 206 | 207 | expect(firstValue).toBe(1) 208 | expect(secondValue).toBe(2) 209 | expect(thirdValue).toBe(3) 210 | expect(lastValue).toBe(5) 211 | } 212 | } 213 | 214 | @Test(expected = IndexOutOfBoundsException::class) 215 | fun argumentCaptor_callPropertyNotAvailable() { 216 | /* Given */ 217 | val m: Methods = mock() 218 | 219 | /* When */ 220 | m.int(1) 221 | 222 | /* Then */ 223 | argumentCaptor().apply { 224 | verify(m).int(capture()) 225 | 226 | expect(secondValue).toBe(2) 227 | } 228 | } 229 | 230 | @Test 231 | fun argumentCaptor_withSingleValue_lambda() { 232 | /* Given */ 233 | val date: Date = mock() 234 | 235 | /* When */ 236 | date.time = 5L 237 | 238 | /* Then */ 239 | argumentCaptor { 240 | verify(date).time = capture() 241 | expect(lastValue).toBe(5L) 242 | } 243 | } 244 | 245 | @Test 246 | fun argumentCaptor_withSingleValue_lambda_properlyFails() { 247 | /* Given */ 248 | val date: Date = mock() 249 | 250 | /* When */ 251 | date.time = 5L 252 | 253 | /* Then */ 254 | expectErrorWithMessage("Expected: 3 but was: 5") on { 255 | argumentCaptor { 256 | verify(date).time = capture() 257 | expect(lastValue).toBe(3L) 258 | } 259 | } 260 | } 261 | 262 | @Test 263 | fun argumentCaptor_vararg() { 264 | /* Given */ 265 | val m: Methods = mock() 266 | 267 | /* When */ 268 | m.varargBooleanResult("a", "b", "c") 269 | 270 | /* Then */ 271 | val captor = argumentCaptor>() 272 | verify(m).varargBooleanResult(*captor.capture()) 273 | expect(captor.firstValue.toList()).toBe(listOf("a", "b", "c")) 274 | } 275 | 276 | @Test 277 | fun argumentCaptor_empty_vararg() { 278 | /* Given */ 279 | val m: Methods = mock() 280 | 281 | /* When */ 282 | m.varargBooleanResult() 283 | 284 | /* Then */ 285 | val captor = argumentCaptor>() 286 | verify(m).varargBooleanResult(*captor.capture()) 287 | expect(captor.firstValue.toList()).toBe(listOf()) 288 | } 289 | 290 | @Test 291 | fun argumentCaptor_arg_vararg() { 292 | /* Given */ 293 | val m: Methods = mock() 294 | 295 | /* When */ 296 | m.argAndVararg("first", "a", "b", "c") 297 | 298 | /* Then */ 299 | val captor = argumentCaptor>() 300 | verify(m).argAndVararg(any(), *captor.capture()) 301 | expect(captor.firstValue.toList()).toBe(listOf("a", "b", "c")) 302 | } 303 | 304 | @Test 305 | fun argumentCaptor_intarray() { 306 | /* Given */ 307 | val m: Methods = mock() 308 | 309 | /* When */ 310 | m.intArray(intArrayOf(1, 2, 3)) 311 | 312 | /* Then */ 313 | val captor = argumentCaptor() 314 | verify(m).intArray(captor.capture()) 315 | expect(captor.firstValue.toList()).toBe(listOf(1, 2, 3)) 316 | } 317 | 318 | @Test 319 | fun argumentCaptor_array() { 320 | /* Given */ 321 | val m: Methods = mock() 322 | 323 | /* When */ 324 | m.stringArray(arrayOf("a", "b", "c")) 325 | 326 | /* Then */ 327 | val captor = argumentCaptor>() 328 | verify(m).stringArray(captor.capture()) 329 | expect(captor.firstValue.toList()).toBe(listOf("a", "b", "c")) 330 | } 331 | 332 | @Test 333 | fun argumentCaptor_empty_array() { 334 | /* Given */ 335 | val m: Methods = mock() 336 | 337 | /* When */ 338 | m.stringArray(arrayOf()) 339 | 340 | /* Then */ 341 | val captor = argumentCaptor>() 342 | verify(m).stringArray(captor.capture()) 343 | expect(captor.firstValue.toList()).toBe(listOf()) 344 | } 345 | } 346 | -------------------------------------------------------------------------------- /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/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 closed(c: Closed) 48 | fun classClosed(c: Class) 49 | suspend fun coroutinesClosed(c: Closed) 50 | fun closedArray(a: Array) 51 | fun closedNullableArray(a: Array) 52 | fun closedCollection(c: Collection) 53 | fun closedList(c: List) 54 | fun closedStringMap(m: Map) 55 | fun closedSet(s: Set) 56 | fun string(s: String) 57 | fun boolean(b: Boolean) 58 | fun booleanArray(d: BooleanArray) 59 | fun byte(b: Byte) 60 | fun byteArray(b: ByteArray) 61 | fun char(c: Char) 62 | fun charArray(c: CharArray) 63 | fun short(s: Short) 64 | fun shortArray(s: ShortArray) 65 | fun int(i: Int) 66 | fun intArray(i: IntArray) 67 | fun long(l: Long) 68 | fun longArray(l: LongArray) 69 | fun float(f: Float) 70 | fun floatArray(f: FloatArray) 71 | fun double(d: Double) 72 | fun doubleArray(d: DoubleArray) 73 | fun closedVararg(vararg c: Closed) 74 | fun throwableClass(t: ThrowableClass) 75 | fun nullableString(s: String?) 76 | 77 | fun stringResult(): String 78 | fun stringResult(s: String): String 79 | fun nullableStringResult(): String? 80 | fun builderMethod(): Methods 81 | fun varargBooleanResult(vararg values: String): Boolean 82 | suspend fun coroutinesClosedBooleanResult(c: Closed): Boolean 83 | suspend fun coroutinesClassClosedBooleanResult(c: Class): Boolean 84 | fun stringArray(a: Array) 85 | fun argAndVararg(s: String, vararg a: String) 86 | 87 | fun nonDefaultReturnType(): ExtraInterface 88 | 89 | fun valueClass(v: ValueClass?) 90 | fun nestedValueClass(v: NestedValueClass) 91 | } 92 | 93 | @JvmInline 94 | value class ValueClass(private val content: String) 95 | 96 | @JvmInline 97 | value class NestedValueClass(val value: ValueClass) 98 | 99 | interface ExtraInterface 100 | 101 | abstract class ThrowingConstructor { 102 | 103 | constructor() { 104 | error("Error in constructor") 105 | } 106 | } 107 | 108 | abstract class ThrowingConstructorWithArgument { 109 | 110 | constructor(s: String) { 111 | error("Error in constructor: $s") 112 | } 113 | } 114 | 115 | abstract class NonThrowingConstructorWithArgument { 116 | 117 | constructor() { 118 | error("Error in constructor") 119 | } 120 | 121 | @Suppress("UNUSED_PARAMETER") 122 | constructor(s: String) 123 | } 124 | 125 | interface GenericMethods { 126 | fun genericMethod(): T 127 | fun nullableReturnType(): T? 128 | } 129 | 130 | class ThrowableClass(cause: Throwable) : Throwable(cause) 131 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 kotlinx.coroutines.test.runTest 6 | import org.junit.Test 7 | import org.mockito.ArgumentMatcher 8 | import org.mockito.invocation.InvocationOnMock 9 | import org.mockito.kotlin.* 10 | import org.mockito.stubbing.Answer 11 | import java.io.IOException 12 | 13 | class MatchersTest : TestBase() { 14 | 15 | @Test 16 | fun anyString() { 17 | mock().apply { 18 | string("") 19 | verify(this).string(any()) 20 | } 21 | } 22 | 23 | @Test 24 | fun anyInt() { 25 | mock().apply { 26 | int(3) 27 | verify(this).int(any()) 28 | } 29 | } 30 | 31 | @Test 32 | fun anyClosedClass() { 33 | mock().apply { 34 | closed(Closed()) 35 | verify(this).closed(any()) 36 | } 37 | } 38 | 39 | @Test 40 | fun anyClassClosedClass() { 41 | mock().apply { 42 | classClosed(Closed::class.java) 43 | verify(this).classClosed(any()) 44 | } 45 | } 46 | 47 | @Test 48 | fun anyCoroutinesClosedClass() { 49 | mock().apply { 50 | runTest { 51 | coroutinesClosed(Closed()) 52 | verify(this@apply).coroutinesClosed(any()) 53 | } 54 | } 55 | } 56 | 57 | @Test 58 | fun anyIntArray() { 59 | mock().apply { 60 | intArray(intArrayOf()) 61 | verify(this).intArray(any()) 62 | } 63 | } 64 | 65 | @Test 66 | fun anyClassArray() { 67 | mock().apply { 68 | closedArray(arrayOf(Closed())) 69 | verify(this).closedArray(anyArray()) 70 | } 71 | } 72 | 73 | @Test 74 | fun anyNullableClassArray() { 75 | mock().apply { 76 | closedNullableArray(arrayOf(Closed(), null)) 77 | verify(this).closedNullableArray(anyArray()) 78 | } 79 | } 80 | 81 | @Test 82 | fun anyStringVararg() { 83 | mock().apply { 84 | closedVararg(Closed(), Closed()) 85 | verify(this).closedVararg(anyVararg()) 86 | } 87 | } 88 | 89 | @Test 90 | fun anyVarargMatching() { 91 | mock().apply { 92 | whenever(varargBooleanResult(anyVararg())).thenReturn(true) 93 | expect(varargBooleanResult()).toBe(true) 94 | } 95 | } 96 | 97 | @Test 98 | fun anyNull_neverVerifiesAny() { 99 | mock().apply { 100 | nullableString(null) 101 | verify(this, never()).nullableString(any()) 102 | } 103 | } 104 | 105 | @Test 106 | fun anyNull_verifiesAnyOrNull() { 107 | mock().apply { 108 | nullableString(null) 109 | verify(this).nullableString(anyOrNull()) 110 | } 111 | } 112 | 113 | @Test 114 | fun anyNull_forPrimitiveBoolean() { 115 | mock().apply { 116 | boolean(false) 117 | verify(this).boolean(anyOrNull()) 118 | } 119 | } 120 | 121 | @Test 122 | fun anyNull_forPrimitiveByte() { 123 | mock().apply { 124 | byte(3) 125 | verify(this).byte(anyOrNull()) 126 | } 127 | } 128 | 129 | @Test 130 | fun anyNull_forPrimitiveChar() { 131 | mock().apply { 132 | char('a') 133 | verify(this).char(anyOrNull()) 134 | } 135 | } 136 | 137 | @Test 138 | fun anyNull_forPrimitiveShort() { 139 | mock().apply { 140 | short(3) 141 | verify(this).short(anyOrNull()) 142 | } 143 | } 144 | 145 | @Test 146 | fun anyNull_forPrimitiveInt() { 147 | mock().apply { 148 | int(3) 149 | verify(this).int(anyOrNull()) 150 | } 151 | } 152 | 153 | @Test 154 | fun anyNull_forPrimitiveLong() { 155 | mock().apply { 156 | long(3) 157 | verify(this).long(anyOrNull()) 158 | } 159 | } 160 | 161 | @Test 162 | fun anyNull_forPrimitiveFloat() { 163 | mock().apply { 164 | float(3f) 165 | verify(this).float(anyOrNull()) 166 | } 167 | } 168 | 169 | @Test 170 | fun anyNull_forPrimitiveDouble() { 171 | mock().apply { 172 | double(3.0) 173 | verify(this).double(anyOrNull()) 174 | } 175 | } 176 | 177 | /** https://github.com/nhaarman/mockito-kotlin/issues/27 */ 178 | @Test 179 | fun anyThrowableWithSingleThrowableConstructor() { 180 | mock().apply { 181 | throwableClass(ThrowableClass(IOException())) 182 | verify(this).throwableClass(any()) 183 | } 184 | } 185 | 186 | @Test 187 | fun listArgThat() { 188 | mock().apply { 189 | closedList(listOf(Closed(), Closed())) 190 | verify(this).closedList( 191 | argThat { 192 | size == 2 193 | } 194 | ) 195 | } 196 | } 197 | 198 | @Test 199 | fun listArgForWhich() { 200 | mock().apply { 201 | closedList(listOf(Closed(), Closed())) 202 | verify(this).closedList( 203 | argForWhich { 204 | size == 2 205 | } 206 | ) 207 | } 208 | } 209 | 210 | @Test 211 | fun listArgWhere() { 212 | mock().apply { 213 | closedList(listOf(Closed(), Closed())) 214 | verify(this).closedList( 215 | argWhere { 216 | it.size == 2 217 | } 218 | ) 219 | } 220 | } 221 | 222 | @Test 223 | fun listArgCheck() { 224 | mock().apply { 225 | closedList(listOf(Closed(), Closed())) 226 | verify(this).closedList( 227 | check { 228 | expect(it.size).toBe(2) 229 | } 230 | ) 231 | } 232 | } 233 | 234 | @Test 235 | fun checkProperlyFails() { 236 | mock().apply { 237 | closedList(listOf(Closed(), Closed())) 238 | 239 | expectErrorWithMessage("Argument(s) are different!") on { 240 | verify(this).closedList( 241 | check { 242 | expect(it.size).toBe(1) 243 | } 244 | ) 245 | } 246 | } 247 | } 248 | 249 | @Test 250 | fun checkWithNullArgument_throwsError() { 251 | mock().apply { 252 | nullableString(null) 253 | 254 | expectErrorWithMessage("null").on { 255 | verify(this).nullableString(check {}) 256 | } 257 | } 258 | } 259 | 260 | @Test 261 | fun isA_withNonNullableString() { 262 | mock().apply { 263 | string("") 264 | verify(this).string(isA()) 265 | } 266 | } 267 | 268 | @Test 269 | fun isA_withNullableString() { 270 | mock().apply { 271 | nullableString("") 272 | verify(this).nullableString(isA()) 273 | } 274 | } 275 | 276 | @Test 277 | fun same_withNonNullArgument() { 278 | mock().apply { 279 | string("") 280 | verify(this).string(same("")) 281 | } 282 | } 283 | 284 | @Test 285 | fun same_withNullableNonNullArgument() { 286 | mock().apply { 287 | nullableString("") 288 | verify(this).nullableString(same("")) 289 | } 290 | } 291 | 292 | @Test 293 | fun same_withNullArgument() { 294 | mock().apply { 295 | nullableString(null) 296 | verify(this).nullableString(same(null)) 297 | } 298 | } 299 | 300 | @Test 301 | fun testVarargAnySuccess() { 302 | /* Given */ 303 | val t = mock() 304 | // a matcher to check if any of the varargs was equals to "b" 305 | val matcher = VarargAnyMatcher({ "b" == it }, String::class.java, true, false) 306 | 307 | /* When */ 308 | whenever(t.varargBooleanResult(argThat(matcher))).thenAnswer(matcher) 309 | 310 | /* Then */ 311 | expect(t.varargBooleanResult("a", "b", "c")).toBe(true) 312 | } 313 | 314 | @Test 315 | fun testVarargAnyFail() { 316 | /* Given */ 317 | val t = mock() 318 | // a matcher to check if any of the varargs was equals to "d" 319 | val matcher = VarargAnyMatcher({ "d" == it }, String::class.java, true, false) 320 | 321 | /* When */ 322 | whenever(t.varargBooleanResult(argThat(matcher))).thenAnswer(matcher) 323 | 324 | /* Then */ 325 | expect(t.varargBooleanResult("a", "b", "c")).toBe(false) 326 | } 327 | 328 | /** https://github.com/nhaarman/mockito-kotlin/issues/328 */ 329 | @Test 330 | fun testRefEqForNonNullableParameter() { 331 | mock().apply { 332 | /* When */ 333 | val array = intArrayOf(2, 3) 334 | intArray(array) 335 | 336 | /* Then */ 337 | verify(this).intArray(refEq(array)) 338 | } 339 | } 340 | 341 | @Test 342 | fun any_forValueClass() { 343 | mock().apply { 344 | valueClass(ValueClass("Content")) 345 | verify(this).valueClass(any()) 346 | } 347 | } 348 | 349 | @Test 350 | fun anyOrNull_forValueClass() { 351 | mock().apply { 352 | valueClass(ValueClass("Content")) 353 | verify(this).valueClass(anyOrNull()) 354 | } 355 | } 356 | 357 | @Test 358 | fun anyOrNull_forValueClass_withNull() { 359 | mock().apply { 360 | valueClass(null) 361 | verify(this).valueClass(anyOrNull()) 362 | } 363 | } 364 | 365 | @Test 366 | fun anyValueClass_withValueClass() { 367 | mock().apply { 368 | valueClass(ValueClass("Content")) 369 | verify(this).valueClass(anyValueClass()) 370 | } 371 | } 372 | 373 | @Test 374 | fun anyValueClass_withNonValueClass() { 375 | expectErrorWithMessage("kotlin.Float is not a value class.") on { 376 | mock().apply { 377 | float(10f) 378 | // Should throw an error because Float is not a value class 379 | float(anyValueClass()) 380 | } 381 | } 382 | } 383 | 384 | @Test 385 | fun anyValueClass_withNestedValueClass() { 386 | mock().apply { 387 | nestedValueClass(NestedValueClass(ValueClass("Content"))) 388 | verify(this).nestedValueClass(anyValueClass()) 389 | } 390 | } 391 | 392 | /** 393 | * a VarargMatcher implementation for varargs of type [T] that will answer with type [R] if any of the var args 394 | * matched. Needs to keep state between matching invocations. 395 | */ 396 | private class VarargAnyMatcher( 397 | private val match: ((T) -> Boolean), 398 | private val clazz: Class, 399 | private val success: R, 400 | private val failure: R 401 | ) : ArgumentMatcher, Answer { 402 | private var anyMatched = false 403 | 404 | override fun matches(t: T): Boolean { 405 | @Suppress("UNCHECKED_CAST") // No idea how to solve this better 406 | anyMatched = (t as Array).any(match) 407 | return anyMatched 408 | } 409 | 410 | override fun answer(i: InvocationOnMock) = if (anyMatched) success else failure 411 | 412 | override fun type(): Class<*> = java.lang.reflect.Array.newInstance(clazz, 0).javaClass 413 | } 414 | } 415 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 kotlinx.coroutines.test.runTest 7 | import org.mockito.kotlin.UseConstructor.Companion.parameterless 8 | import org.mockito.kotlin.UseConstructor.Companion.withArguments 9 | import org.mockito.kotlin.doReturn 10 | import org.mockito.kotlin.mock 11 | import org.mockito.kotlin.verify 12 | import org.mockito.kotlin.whenever 13 | import org.mockito.kotlin.any 14 | import org.junit.Test 15 | import org.mockito.Mockito 16 | import org.mockito.exceptions.verification.WantedButNotInvoked 17 | import org.mockito.invocation.DescribedInvocation 18 | import org.mockito.kotlin.argumentCaptor 19 | import org.mockito.listeners.InvocationListener 20 | import org.mockito.mock.SerializableMode.BASIC 21 | import java.io.PrintStream 22 | import java.io.Serializable 23 | import java.util.* 24 | 25 | class MockingTest : TestBase() { 26 | 27 | private lateinit var propertyInterfaceVariable: MyInterface 28 | private lateinit var propertyClassVariable: MyClass 29 | 30 | @Test 31 | fun localInterfaceValue() { 32 | /* When */ 33 | val instance: MyInterface = mock() 34 | 35 | /* Then */ 36 | expect(instance).toNotBeNull() 37 | } 38 | 39 | @Test 40 | fun propertyInterfaceVariable() { 41 | /* When */ 42 | propertyInterfaceVariable = mock() 43 | 44 | /* Then */ 45 | expect(propertyInterfaceVariable).toNotBeNull() 46 | } 47 | 48 | @Test 49 | fun localClassValue() { 50 | /* When */ 51 | val instance: MyClass = mock() 52 | 53 | /* Then */ 54 | expect(instance).toNotBeNull() 55 | } 56 | 57 | @Test 58 | fun propertyClassVariable() { 59 | /* When */ 60 | propertyClassVariable = mock() 61 | 62 | /* Then */ 63 | expect(propertyClassVariable).toNotBeNull() 64 | } 65 | 66 | @Test 67 | fun untypedVariable() { 68 | /* When */ 69 | val instance = mock() 70 | 71 | expect(instance).toNotBeNull() 72 | } 73 | 74 | @Test 75 | fun deepStubs() { 76 | val cal: Calendar = mock(defaultAnswer = Mockito.RETURNS_DEEP_STUBS) 77 | whenever(cal.time.time).thenReturn(123L) 78 | expect(cal.time.time).toBe(123L) 79 | } 80 | 81 | @Test 82 | fun testMockStubbing_lambda() { 83 | /* Given */ 84 | val mock = mock() { 85 | on { stringResult() } doReturn "A" 86 | } 87 | 88 | /* When */ 89 | val result = mock.stringResult() 90 | 91 | /* Then */ 92 | expect(result).toBe("A") 93 | } 94 | 95 | @Test 96 | fun testMockStubbing_normalOverridesLambda() { 97 | /* Given */ 98 | val mock = mock() { 99 | on { stringResult() }.doReturn("A") 100 | } 101 | whenever(mock.stringResult()).thenReturn("B") 102 | 103 | /* When */ 104 | val result = mock.stringResult() 105 | 106 | /* Then */ 107 | expect(result).toBe("B") 108 | } 109 | 110 | @Test 111 | fun mock_withCustomDefaultAnswer_parameterName() { 112 | /* Given */ 113 | val mock = mock(defaultAnswer = Mockito.RETURNS_SELF) 114 | 115 | /* When */ 116 | val result = mock.builderMethod() 117 | 118 | /* Then */ 119 | expect(result).toBe(mock) 120 | } 121 | 122 | @Test 123 | fun mock_withSettingsAPI_extraInterfaces() { 124 | /* Given */ 125 | val mock = mock( 126 | extraInterfaces = arrayOf(ExtraInterface::class) 127 | ) 128 | 129 | /* Then */ 130 | expect(mock).toBeInstanceOf() 131 | } 132 | 133 | @Test 134 | fun mock_withSettingsAPI_name() { 135 | /* Given */ 136 | val mock = mock(name = "myName") 137 | 138 | /* When */ 139 | expectErrorWithMessage("myName.stringResult()") on { 140 | verify(mock).stringResult() 141 | } 142 | } 143 | 144 | @Test 145 | fun mock_withSettingsAPI_defaultAnswer() { 146 | /* Given */ 147 | val mock = mock(defaultAnswer = Mockito.RETURNS_MOCKS) 148 | 149 | /* When */ 150 | val result = mock.nonDefaultReturnType() 151 | 152 | /* Then */ 153 | expect(result).toNotBeNull() 154 | } 155 | 156 | @Test 157 | fun mock_withSettingsAPI_serializable() { 158 | /* Given */ 159 | val mock = mock(serializable = true) 160 | 161 | /* Then */ 162 | expect(mock).toBeInstanceOf() 163 | } 164 | 165 | @Test 166 | fun mock_withSettingsAPI_serializableMode() { 167 | /* Given */ 168 | val mock = mock(serializableMode = BASIC) 169 | 170 | /* Then */ 171 | expect(mock).toBeInstanceOf() 172 | } 173 | 174 | @Test 175 | fun mock_withSettingsAPI_verboseLogging() { 176 | /* Given */ 177 | val out = mock() 178 | System.setOut(out) 179 | val mock = mock(verboseLogging = true) 180 | 181 | try { 182 | /* When */ 183 | verify(mock).stringResult() 184 | fail("Expected an exception") 185 | } catch (e: WantedButNotInvoked) { 186 | /* Then */ 187 | argumentCaptor().apply { 188 | verify(out).println(capture()) 189 | expect(lastValue.toString()).toBe("methods.stringResult();") 190 | } 191 | } 192 | } 193 | 194 | @Test 195 | fun mock_withSettingsAPI_invocationListeners() { 196 | /* Given */ 197 | var bool = false 198 | val mock = mock(invocationListeners = arrayOf(InvocationListener { bool = true })) 199 | 200 | /* When */ 201 | mock.stringResult() 202 | 203 | /* Then */ 204 | expect(bool).toHold() 205 | } 206 | 207 | @Test 208 | fun mock_withSettingsAPI_stubOnly() { 209 | /* Given */ 210 | val mock = mock(stubOnly = true) 211 | 212 | /* Expect */ 213 | expectErrorWithMessage("is a stubOnly() mock") on { 214 | 215 | /* When */ 216 | verify(mock).stringResult() 217 | } 218 | } 219 | 220 | @Test 221 | fun mock_withSettingsAPI_useConstructor() { 222 | /* Given */ 223 | expectErrorWithMessage("Unable to create mock instance of type ") on { 224 | mock(useConstructor = parameterless()) {} 225 | } 226 | } 227 | 228 | @Test 229 | fun mock_withSettingsAPI_useConstructorWithArguments_failing() { 230 | /* Given */ 231 | expectErrorWithMessage("Unable to create mock instance of type ") on { 232 | mock(useConstructor = withArguments("Test")) {} 233 | } 234 | } 235 | 236 | @Test 237 | fun mock_withSettingsAPI_useConstructorWithArguments() { 238 | /* When */ 239 | val result = mock(useConstructor = withArguments("Test")) {} 240 | 241 | /* Then */ 242 | expect(result).toNotBeNull() 243 | } 244 | 245 | @Test 246 | fun mockStubbing_withSettingsAPI_extraInterfaces() { 247 | /* Given */ 248 | val mock = mock(extraInterfaces = arrayOf(ExtraInterface::class)) {} 249 | 250 | /* Then */ 251 | expect(mock).toBeInstanceOf() 252 | } 253 | 254 | @Test 255 | fun mockStubbing_withSettingsAPI_name() { 256 | /* Given */ 257 | val mock = mock(name = "myName") {} 258 | 259 | /* When */ 260 | expectErrorWithMessage("myName.stringResult()") on { 261 | verify(mock).stringResult() 262 | } 263 | } 264 | 265 | @Test 266 | fun mockStubbing_withSettingsAPIAndStubbing_name() { 267 | /* Given */ 268 | val mock = mock(name = "myName") { 269 | on { nullableStringResult() } doReturn "foo" 270 | } 271 | 272 | /* When */ 273 | val result = mock.nullableStringResult() 274 | 275 | /* Then */ 276 | expect(result).toBe("foo") 277 | } 278 | 279 | @Test 280 | fun mockCoroutines_withClosedBooleanReturn_name() = runTest { 281 | /* Given */ 282 | val mock = mock(name = "myName") { 283 | onBlocking { coroutinesClosedBooleanResult(any()) } doReturn true 284 | } 285 | 286 | /* When */ 287 | val result = mock.coroutinesClosedBooleanResult(Closed()) 288 | 289 | /* Then */ 290 | expect(result).toBe(true) 291 | } 292 | 293 | @Test 294 | fun mockCoroutines_withClassClosedBooleanReturn_name() = runTest { 295 | /* Given */ 296 | val mock = mock(name = "myName") { 297 | onBlocking { coroutinesClassClosedBooleanResult(any()) } doReturn true 298 | } 299 | 300 | /* When */ 301 | val result = mock.coroutinesClassClosedBooleanResult(Closed::class.java) 302 | 303 | /* Then */ 304 | expect(result).toBe(true) 305 | } 306 | 307 | @Test 308 | fun mockStubbing_withSettingsAPI_defaultAnswer() { 309 | /* Given */ 310 | val mock = mock(defaultAnswer = Mockito.RETURNS_MOCKS) {} 311 | 312 | /* When */ 313 | val result = mock.nonDefaultReturnType() 314 | 315 | /* Then */ 316 | expect(result).toNotBeNull() 317 | } 318 | 319 | @Test 320 | fun mockStubbing_withSettingsAPI_serializable() { 321 | /* Given */ 322 | val mock = mock(serializable = true) {} 323 | 324 | /* Then */ 325 | expect(mock).toBeInstanceOf() 326 | } 327 | 328 | @Test 329 | fun mockStubbing_withSettingsAPI_serializableMode() { 330 | /* Given */ 331 | val mock = mock(serializableMode = BASIC) {} 332 | 333 | /* Then */ 334 | expect(mock).toBeInstanceOf() 335 | } 336 | 337 | @Test 338 | fun mockStubbing_withSettingsAPI_verboseLogging() { 339 | /* Given */ 340 | val out = mock() 341 | System.setOut(out) 342 | val mock = mock(verboseLogging = true) {} 343 | 344 | try { 345 | /* When */ 346 | verify(mock).stringResult() 347 | fail("Expected an exception") 348 | } catch (e: WantedButNotInvoked) { 349 | /* Then */ 350 | argumentCaptor().apply { 351 | verify(out).println(capture()) 352 | expect(lastValue.toString()).toBe("methods.stringResult();") 353 | } 354 | } 355 | } 356 | 357 | @Test 358 | fun mockStubbing_withSettingsAPI_invocationListeners() { 359 | /* Given */ 360 | var bool = false 361 | val mock = mock(invocationListeners = arrayOf(InvocationListener { bool = true })) {} 362 | 363 | /* When */ 364 | mock.stringResult() 365 | 366 | /* Then */ 367 | expect(bool).toHold() 368 | } 369 | 370 | @Test 371 | fun mockStubbing_withSettingsAPI_stubOnly() { 372 | /* Given */ 373 | val mock = mock(stubOnly = true) {} 374 | 375 | /* Expect */ 376 | expectErrorWithMessage("is a stubOnly() mock") on { 377 | 378 | /* When */ 379 | verify(mock).stringResult() 380 | } 381 | } 382 | 383 | @Test 384 | fun mockStubbing_withSettingsAPI_useConstructor() { 385 | /* Given */ 386 | expectErrorWithMessage("Unable to create mock instance of type ") on { 387 | mock(useConstructor = parameterless()) {} 388 | } 389 | } 390 | 391 | private interface MyInterface 392 | private open class MyClass 393 | } 394 | -------------------------------------------------------------------------------- /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 testOngoingStubbing_doAnswer_withDestructuredArgument() { 206 | /* Given */ 207 | val mock = mock { 208 | on { stringResult(any()) } doAnswer { (s: String) -> "$s-result" } 209 | } 210 | 211 | /* When */ 212 | val result = mock.stringResult("argument") 213 | 214 | /* Then */ 215 | expect(result).toBe("argument-result") 216 | } 217 | 218 | @Test 219 | fun testOngoingStubbing_doAnswer_withDestructuredArguments() { 220 | /* Given */ 221 | val mock = mock { 222 | on { varargBooleanResult(any(), any()) } doAnswer { (a: String, b: String) -> 223 | a == b.trim() 224 | } 225 | } 226 | 227 | /* When */ 228 | val result = mock.varargBooleanResult("argument", " argument ") 229 | 230 | /* Then */ 231 | expect(result).toBe(true) 232 | } 233 | 234 | @Test 235 | fun testMockStubbingAfterCreatingMock() { 236 | val mock = mock() 237 | 238 | //create stub after creation of mock 239 | mock.stub { 240 | on { stringResult() } doReturn "result" 241 | } 242 | 243 | /* When */ 244 | val result = mock.stringResult() 245 | 246 | /* Then */ 247 | expect(result).toBe("result") 248 | } 249 | 250 | @Test 251 | fun testOverrideDefaultStub() { 252 | /* Given mock with stub */ 253 | val mock = mock { 254 | on { stringResult() } doReturn "result1" 255 | } 256 | 257 | /* override stub */ 258 | mock.stub { 259 | on { stringResult() } doReturn "result2" 260 | } 261 | 262 | /* When */ 263 | val result = mock.stringResult() 264 | 265 | /* Then */ 266 | expect(result).toBe("result2") 267 | } 268 | 269 | @Test 270 | fun stubbingTwiceWithArgumentMatchers() { 271 | /* When */ 272 | val mock = mock { 273 | on { stringResult(argThat { this == "A" }) } doReturn "A" 274 | on { stringResult(argThat { this == "B" }) } doReturn "B" 275 | } 276 | 277 | /* Then */ 278 | expect(mock.stringResult("A")).toBe("A") 279 | expect(mock.stringResult("B")).toBe("B") 280 | } 281 | 282 | @Test 283 | fun stubbingRealObject() { 284 | val notAMock = "" 285 | 286 | /* Expect */ 287 | expectErrorWithMessage("is not a mock!").on { 288 | notAMock.stub { } 289 | } 290 | } 291 | 292 | @Test 293 | fun stubbingTwiceWithCheckArgumentMatchers_throwsException() { 294 | /* Expect */ 295 | expectErrorWithMessage("null").on { 296 | mock { 297 | on { stringResult(check { }) } doReturn "A" 298 | on { stringResult(check { }) } doReturn "B" 299 | } 300 | } 301 | } 302 | 303 | @Test 304 | fun doReturn_withSingleItemList() { 305 | /* Given */ 306 | val mock = mock { 307 | on { stringResult() } doReturnConsecutively listOf("a", "b") 308 | } 309 | 310 | /* Then */ 311 | expect(mock.stringResult()).toBe("a") 312 | expect(mock.stringResult()).toBe("b") 313 | } 314 | 315 | @Test 316 | fun doReturn_throwsNPE() { 317 | assumeFalse(mockMakerInlineEnabled()) 318 | expectErrorWithMessage("look at the stack trace below") on { 319 | 320 | /* When */ 321 | mock { 322 | on { throwsNPE() } doReturn "result" 323 | } 324 | } 325 | } 326 | 327 | @Test 328 | fun doReturn_withGenericIntReturnType_on() { 329 | /* When */ 330 | val mock = mock> { 331 | on { genericMethod() } doReturn 2 332 | } 333 | 334 | /* Then */ 335 | expect(mock.genericMethod()).toBe(2) 336 | } 337 | 338 | @Test 339 | fun doReturn_withGenericIntReturnType_onGeneric() { 340 | /* Given */ 341 | val mock = mock> { 342 | onGeneric { genericMethod() } doReturn 2 343 | } 344 | 345 | /* Then */ 346 | expect(mock.genericMethod()).toBe(2) 347 | } 348 | 349 | @Test 350 | fun doReturn_withGenericNullableReturnType_onGeneric() { 351 | val m = mock> { 352 | onGeneric { nullableReturnType() } doReturn "Test" 353 | } 354 | 355 | expect(m.nullableReturnType()).toBe("Test") 356 | } 357 | 358 | @Test 359 | fun stubbingExistingMock() { 360 | /* Given */ 361 | val mock = mock() 362 | 363 | /* When */ 364 | stubbing(mock) { 365 | on { stringResult() } doReturn "result" 366 | } 367 | 368 | /* Then */ 369 | expect(mock.stringResult()).toBe("result") 370 | } 371 | 372 | @Test 373 | fun testMockitoStackOnUnfinishedStubbing() { 374 | /* Given */ 375 | val mock = mock() 376 | whenever(mock.stringResult()) 377 | 378 | /* When */ 379 | try { 380 | mock.stringResult() 381 | } catch (e: UnfinishedStubbingException) { 382 | /* Then */ 383 | expect(e.message).toContain("Unfinished stubbing detected here:") 384 | expect(e.message).toContain("-> at test.OngoingStubbingTest.testMockitoStackOnUnfinishedStubbing") 385 | } 386 | } 387 | } 388 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /version.properties: -------------------------------------------------------------------------------- 1 | tagPrefix= 2 | --------------------------------------------------------------------------------