Merge remote-tracking branch 'goog/mirror-aosp-main' into
'udc-mainline-prod'
Bug: 308181344
Test: TH
Change-Id: Iff81d3b769a149fc25a8e0ab925f2ab9dfa6f601
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 0000000..ee9389c
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,4 @@
+Thank you for submitting a pull request! But first:
+
+ - [ ] Can you back your code up with tests?
+ - [ ] Keep your commits clean: [squash your commits if necessary](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History).
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..da82e7d
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,106 @@
+#
+# CI build that assembles artifacts and runs tests.
+# If validation is successful this workflow releases from the main dev branch.
+#
+# - skipping CI: add [skip ci] to the commit message
+# - skipping release: add [skip release] to the commit message
+#
+name: CI
+
+on:
+ push:
+ branches:
+ - main
+ tags-ignore:
+ - v* # release tags are automatically generated after a successful CI build, no need to run CI against them
+ pull_request:
+ branches:
+ - main
+
+jobs:
+
+ #
+ # SINGLE-JOB
+ #
+ verify:
+ runs-on: ubuntu-latest
+ if: "! contains(toJSON(github.event.commits.*.message), '[skip ci]')"
+
+ steps:
+
+ - name: 1. Check out code
+ uses: actions/checkout@v2 # https://github.com/actions/checkout
+
+ - name: 2. Set up Java 8
+ uses: actions/setup-java@v1 # https://github.com/actions/setup-java
+ with:
+ java-version: 8
+
+ - name: 3. Validate Gradle wrapper
+ uses: gradle/wrapper-validation-action@v1 # https://github.com/gradle/wrapper-validation-action
+
+ #
+ # Main build job
+ #
+ build:
+ needs: [verify]
+ runs-on: ubuntu-latest
+
+ # Definition of the build matrix
+ strategy:
+ matrix:
+ mock-maker: ['mock-maker-default', 'mock-maker-inline']
+ kotlin: ['1.3.50', '1.4.21']
+ # Note that the old Travis CI referenced other Kotlin versions: '1.0.7', '1.1.61', '1.2.50'
+ # However, those versions of Kotlin don't work with latest Gradle
+
+ steps:
+
+ - name: 1. Check out code
+ uses: actions/checkout@v2 # https://github.com/actions/checkout
+
+ - name: 2. Set up Java 8
+ uses: actions/setup-java@v1 # https://github.com/actions/setup-java
+ with:
+ java-version: 8
+
+ - name: 3. Build with Kotlin ${{ matrix.kotlin }} and mock-maker ${{ matrix.mock-maker }}
+ run: |
+ ops/mockMakerInline.sh
+ ./gradlew build
+ env:
+ KOTLIN_VERSION: ${{ matrix.kotlin }}
+ MOCK_MAKER: ${{ matrix.mock-maker }}
+
+ #
+ # Release job, only for pushes to the main development branch
+ #
+ release:
+ runs-on: ubuntu-latest
+ needs: [build] # build job must pass before we can release
+
+ if: github.event_name == 'push'
+ && github.ref == 'refs/heads/main'
+ && github.repository == 'mockito/mockito-kotlin'
+ && !contains(toJSON(github.event.commits.*.message), '[skip release]')
+
+ steps:
+
+ - name: Check out code
+ uses: actions/checkout@v2 # https://github.com/actions/checkout
+ with:
+ fetch-depth: '0' # https://github.com/shipkit/shipkit-changelog#fetch-depth-on-ci
+
+ - name: Set up Java 8
+ uses: actions/setup-java@v1
+ with:
+ java-version: 8
+
+ - name: Build and release
+ run: ./gradlew githubRelease publishToSonatype closeAndReleaseStagingRepository
+ env:
+ GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
+ NEXUS_TOKEN_USER: ${{secrets.NEXUS_TOKEN_USER}}
+ NEXUS_TOKEN_PWD: ${{secrets.NEXUS_TOKEN_PWD}}
+ PGP_KEY: ${{secrets.PGP_KEY}}
+ PGP_PWD: ${{secrets.PGP_PWD}}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..4b102ff
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,13 @@
+.gradle
+build/
+out/
+repo
+
+# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
+!gradle-wrapper.jar
+
+# intelliJ
+.idea/
+*.iml
+
+*.orig
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..69f8a38
--- /dev/null
+++ b/.idea/codeStyles/Project.xml
@@ -0,0 +1,276 @@
+<component name="ProjectCodeStyleConfiguration">
+ <code_scheme name="Project" version="173">
+ <option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
+ <option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
+ <option name="PACKAGES_TO_USE_IMPORT_ON_DEMAND">
+ <value />
+ </option>
+ <option name="IMPORT_LAYOUT_TABLE">
+ <value>
+ <package name="android" withSubpackages="true" static="false" />
+ <emptyLine />
+ <package name="com" withSubpackages="true" static="false" />
+ <emptyLine />
+ <package name="junit" withSubpackages="true" static="false" />
+ <emptyLine />
+ <package name="net" withSubpackages="true" static="false" />
+ <emptyLine />
+ <package name="org" withSubpackages="true" static="false" />
+ <emptyLine />
+ <package name="java" withSubpackages="true" static="false" />
+ <emptyLine />
+ <package name="javax" withSubpackages="true" static="false" />
+ <emptyLine />
+ <package name="" withSubpackages="true" static="false" />
+ <emptyLine />
+ <package name="" withSubpackages="true" static="true" />
+ <emptyLine />
+ </value>
+ </option>
+ <option name="RIGHT_MARGIN" value="100" />
+ <AndroidXmlCodeStyleSettings>
+ <option name="USE_CUSTOM_SETTINGS" value="true" />
+ </AndroidXmlCodeStyleSettings>
+ <JavaCodeStyleSettings>
+ <option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
+ <option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
+ <option name="PACKAGES_TO_USE_IMPORT_ON_DEMAND">
+ <value />
+ </option>
+ <option name="IMPORT_LAYOUT_TABLE">
+ <value>
+ <package name="android" withSubpackages="true" static="false" />
+ <emptyLine />
+ <package name="com" withSubpackages="true" static="false" />
+ <emptyLine />
+ <package name="junit" withSubpackages="true" static="false" />
+ <emptyLine />
+ <package name="net" withSubpackages="true" static="false" />
+ <emptyLine />
+ <package name="org" withSubpackages="true" static="false" />
+ <emptyLine />
+ <package name="java" withSubpackages="true" static="false" />
+ <emptyLine />
+ <package name="javax" withSubpackages="true" static="false" />
+ <emptyLine />
+ <package name="" withSubpackages="true" static="false" />
+ <emptyLine />
+ <package name="" withSubpackages="true" static="true" />
+ <emptyLine />
+ </value>
+ </option>
+ </JavaCodeStyleSettings>
+ <JetCodeStyleSettings>
+ <option name="IMPORT_NESTED_CLASSES" value="true" />
+ <option name="CONTINUATION_INDENT_IN_PARAMETER_LISTS" value="false" />
+ <option name="CONTINUATION_INDENT_FOR_EXPRESSION_BODIES" value="false" />
+ <option name="CONTINUATION_INDENT_FOR_CHAINED_CALLS" value="false" />
+ </JetCodeStyleSettings>
+ <Objective-C-extensions>
+ <file>
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
+ </file>
+ <class>
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
+ </class>
+ <extensions>
+ <pair source="cpp" header="h" fileNamingConvention="NONE" />
+ <pair source="c" header="h" fileNamingConvention="NONE" />
+ </extensions>
+ </Objective-C-extensions>
+ <XML>
+ <option name="XML_KEEP_LINE_BREAKS" value="false" />
+ <option name="XML_ALIGN_ATTRIBUTES" value="false" />
+ <option name="XML_SPACE_INSIDE_EMPTY_TAG" value="true" />
+ <option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
+ </XML>
+ <codeStyleSettings language="JAVA">
+ <indentOptions>
+ <option name="CONTINUATION_INDENT_SIZE" value="6" />
+ </indentOptions>
+ </codeStyleSettings>
+ <codeStyleSettings language="XML">
+ <option name="FORCE_REARRANGE_MODE" value="1" />
+ <indentOptions>
+ <option name="CONTINUATION_INDENT_SIZE" value="4" />
+ </indentOptions>
+ <arrangement>
+ <rules>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>xmlns:android</NAME>
+ <XML_NAMESPACE>^$</XML_NAMESPACE>
+ </AND>
+ </match>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>xmlns:.*</NAME>
+ <XML_NAMESPACE>^$</XML_NAMESPACE>
+ </AND>
+ </match>
+ <order>BY_NAME</order>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>.*:id</NAME>
+ <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
+ </AND>
+ </match>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>.*:name</NAME>
+ <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
+ </AND>
+ </match>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>name</NAME>
+ <XML_NAMESPACE>^$</XML_NAMESPACE>
+ </AND>
+ </match>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>style</NAME>
+ <XML_NAMESPACE>^$</XML_NAMESPACE>
+ </AND>
+ </match>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>.*</NAME>
+ <XML_NAMESPACE>^$</XML_NAMESPACE>
+ </AND>
+ </match>
+ <order>BY_NAME</order>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>.*:layout_width</NAME>
+ <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
+ </AND>
+ </match>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>.*:layout_height</NAME>
+ <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
+ </AND>
+ </match>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>.*:layout_.*</NAME>
+ <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
+ </AND>
+ </match>
+ <order>BY_NAME</order>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>.*:width</NAME>
+ <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
+ </AND>
+ </match>
+ <order>BY_NAME</order>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>.*:height</NAME>
+ <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
+ </AND>
+ </match>
+ <order>BY_NAME</order>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>.*</NAME>
+ <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
+ </AND>
+ </match>
+ <order>BY_NAME</order>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>.*</NAME>
+ <XML_NAMESPACE>.*</XML_NAMESPACE>
+ </AND>
+ </match>
+ <order>BY_NAME</order>
+ </rule>
+ </section>
+ </rules>
+ </arrangement>
+ </codeStyleSettings>
+ <codeStyleSettings language="kotlin">
+ <option name="ALIGN_MULTILINE_PARAMETERS_IN_CALLS" value="true" />
+ <option name="CALL_PARAMETERS_WRAP" value="5" />
+ <option name="CALL_PARAMETERS_LPAREN_ON_NEXT_LINE" value="true" />
+ <option name="CALL_PARAMETERS_RPAREN_ON_NEXT_LINE" value="true" />
+ <option name="METHOD_PARAMETERS_WRAP" value="5" />
+ <option name="METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE" value="true" />
+ <option name="METHOD_PARAMETERS_RPAREN_ON_NEXT_LINE" value="true" />
+ <option name="EXTENDS_LIST_WRAP" value="1" />
+ <indentOptions>
+ <option name="CONTINUATION_INDENT_SIZE" value="6" />
+ </indentOptions>
+ </codeStyleSettings>
+ </code_scheme>
+</component>
\ No newline at end of file
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..79ee123
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+<component name="ProjectCodeStyleConfiguration">
+ <state>
+ <option name="USE_PER_PROJECT_SETTINGS" value="true" />
+ </state>
+</component>
\ No newline at end of file
diff --git a/.idea/copyright/MIT.xml b/.idea/copyright/MIT.xml
new file mode 100644
index 0000000..63c2a5b
--- /dev/null
+++ b/.idea/copyright/MIT.xml
@@ -0,0 +1,6 @@
+<component name="CopyrightManager">
+ <copyright>
+ <option name="myName" value="MIT" />
+ <option name="notice" value="The MIT License Copyright (c) 2018 Niek Haarman Copyright (c) 2007 Mockito contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE." />
+ </copyright>
+</component>
\ No newline at end of file
diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml
new file mode 100644
index 0000000..57aa1f3
--- /dev/null
+++ b/.idea/copyright/profiles_settings.xml
@@ -0,0 +1,7 @@
+<component name="CopyrightManager">
+ <settings>
+ <module2copyright>
+ <element module="Production" copyright="MIT" />
+ </module2copyright>
+ </settings>
+</component>
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..c33dd39
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,6 @@
+<component name="InspectionProjectProfileManager">
+ <profile version="1.0">
+ <option name="myName" value="Project Default" />
+ <inspection_tool class="CanBeParameter" enabled="false" level="WARNING" enabled_by_default="false" />
+ </profile>
+</component>
\ No newline at end of file
diff --git a/Android.bp b/Android.bp
new file mode 100644
index 0000000..9c7e088
--- /dev/null
+++ b/Android.bp
@@ -0,0 +1,58 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//
+
+package {
+ default_applicable_licenses: ["external_mockito_kotlin_license"],
+}
+
+// Added automatically by a large-scale-change that took the approach of
+// 'apply every license found to every target'. While this makes sure we respect
+// every license restriction, it may not be entirely correct.
+//
+// e.g. GPL in an MIT project might only apply to the contrib/ directory.
+//
+// Please consider splitting the single license below into multiple licenses,
+// taking care not to lose any license_kind information, and overriding the
+// default license using the 'licenses: [...]' property on targets as needed.
+//
+// For unused files, consider creating a 'fileGroup' with "//visibility:private"
+// to attach the license to, and including a comment whether the files may be
+// used in the current project.
+// See: http://go/android-license-faq
+license {
+ name: "external_mockito_kotlin_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ "SPDX-license-identifier-MIT",
+ ],
+ license_text: [
+ "LICENSE",
+ ],
+}
+
+java_library_static {
+ // TODO (b/289573112): mockito-kotlin name is already in use by a WearOS prebuilt.
+ // Rename to mockito-kotlin once that prebuilt is removed.
+ name: "mockito-kotlin2",
+ hostdex: true,
+ srcs: ["mockito-kotlin/src/main/**/*.kt"],
+
+ static_libs: ["mockito", "kotlinx_coroutines"],
+
+ sdk_version: "module_current"
+}
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..8a39ffc
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,22 @@
+The MIT License
+
+Copyright (c) 2016 Niek Haarman
+Copyright (c) 2007 Mockito contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
\ No newline at end of file
diff --git a/METADATA b/METADATA
new file mode 100644
index 0000000..d7158a6
--- /dev/null
+++ b/METADATA
@@ -0,0 +1,14 @@
+name: "mockito-kotlin"
+description:
+ "Mockito for Kotlin"
+
+third_party {
+ url {
+ type: GIT
+ value: "https://github.com/mockito/mockito-kotlin"
+ }
+ version: "2.2.11"
+ last_upgrade_date { year: 2023 month: 6 day: 13 }
+ license_type: NOTICE
+}
+
diff --git a/MODULE_LICENSE_MIT b/MODULE_LICENSE_MIT
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/MODULE_LICENSE_MIT
diff --git a/OWNERS b/OWNERS
new file mode 100644
index 0000000..88f0700
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1,2 @@
+romam@google.com
+farivar@google.com
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..abac3de
--- /dev/null
+++ b/README.md
@@ -0,0 +1,72 @@
+# Mockito-Kotlin
+[ ![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)
+
+A small library that provides helper functions to work with [Mockito](https://github.com/mockito/mockito) in Kotlin.
+
+## Install
+
+Mockito-Kotlin is available on Maven Central and JCenter.
+For Gradle users, add the following to your `build.gradle`, replacing `x.x.x` with the latest version:
+
+```groovy
+testImplementation "org.mockito.kotlin:mockito-kotlin:x.x.x"
+```
+
+## Example
+
+A test using Mockito-Kotlin typically looks like the following:
+
+```kotlin
+@Test
+fun doAction_doesSomething(){
+ /* Given */
+ val mock = mock<MyClass> {
+ on { getText() } doReturn "text"
+ }
+ val classUnderTest = ClassUnderTest(mock)
+
+ /* When */
+ classUnderTest.doAction()
+
+ /* Then */
+ verify(mock).doSomething(any())
+}
+```
+
+For more info and samples, see the [Wiki](https://github.com/mockito/mockito-kotlin/wiki).
+
+## Building
+
+Mockito-Kotlin is built with Gradle.
+
+ - `./gradlew build` builds the project
+ - `./gradlew publishToMavenLocal` installs the maven artifacts in your local repository
+ - `./gradlew assemble && ./gradlew test` runs the test suite (See Testing below)
+
+### Versioning
+
+Mockito-Kotlin roughly follows SEMVER; version names are parsed from
+git tags using `git describe`.
+
+### Testing
+
+Mockito-Kotlin's test suite is located in a separate `tests` module,
+to allow running the tests using several Kotlin versions whilst still
+keeping the base module at a recent version.
+
+Testing thus must be done in two stages: one to build the base artifact
+to test against, and the actual execution of the tests against the
+built artifact:
+
+ - `./gradlew assemble` builds the base artifact
+ - `./gradlew test` runs the tests against the built artifact.
+
+Usually it is enough to test only using the default Kotlin versions;
+CI will test against multiple versions.
+If you want to test using a different Kotlin version locally, set
+an environment variable `KOTLIN_VERSION` and run the tests.
+
+### Acknowledgements
+
+`mockito-kotlin` was created and developed by [nhaarman@](https://github.com/nhaarman) after which the repository was integrated into the official Mockito GitHub organization.
+We would like to thank Niek for the original idea and extensive work plus support that went into `mockito-kotlin`.
diff --git a/RELEASING.md b/RELEASING.md
new file mode 100644
index 0000000..3f0140c
--- /dev/null
+++ b/RELEASING.md
@@ -0,0 +1,3 @@
+# Releasing
+
+Every change on the main development branch is released to Maven Central.
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..3e55fa8
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,54 @@
+buildscript {
+ repositories {
+ mavenLocal() // for local testing
+ maven { url "https://plugins.gradle.org/m2/" }
+ }
+ dependencies {
+ classpath "org.shipkit:shipkit-changelog:1.+"
+ classpath "org.shipkit:shipkit-auto-version:1.+"
+ }
+}
+
+plugins {
+ id "io.github.gradle-nexus.publish-plugin" version "1.0.0"
+}
+
+apply plugin: "org.shipkit.shipkit-auto-version"
+apply plugin: "org.shipkit.shipkit-changelog"
+apply plugin: "org.shipkit.shipkit-github-release"
+
+allprojects {
+ group = 'org.mockito.kotlin'
+}
+
+tasks.named("generateChangelog") {
+ previousRevision = project.ext.'shipkit-auto-version.previous-tag'
+ githubToken = System.getenv("GITHUB_TOKEN")
+ repository = "mockito/mockito-kotlin"
+ releaseTag = project.version
+}
+
+tasks.named("githubRelease") {
+ def genTask = tasks.named("generateChangelog").get()
+ dependsOn genTask
+ repository = genTask.repository
+ changelog = genTask.outputFile
+ githubToken = System.getenv("GITHUB_TOKEN")
+ newTagRevision = System.getenv("GITHUB_SHA")
+ releaseTag = project.version
+ releaseName = project.version
+}
+
+nexusPublishing {
+ repositories {
+ if (System.getenv("NEXUS_TOKEN_PWD")) {
+ sonatype { // Publishing to: https://s01.oss.sonatype.org (faster instance)
+ nexusUrl = uri("https://s01.oss.sonatype.org/service/local/")
+ snapshotRepositoryUrl = uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")
+
+ username = System.getenv("NEXUS_TOKEN_USER")
+ password = System.getenv("NEXUS_TOKEN_PWD")
+ }
+ }
+ }
+}
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000..5d8bda0
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1 @@
+isRelease=false
diff --git a/gradle/publishing.gradle b/gradle/publishing.gradle
new file mode 100644
index 0000000..6bb5f1a
--- /dev/null
+++ b/gradle/publishing.gradle
@@ -0,0 +1,69 @@
+apply plugin: 'maven-publish'
+
+task javadocJar(type: Jar, dependsOn: javadoc) {
+ classifier = 'javadoc'
+ from 'build/javadoc'
+}
+
+task sourceJar(type: Jar) {
+ from sourceSets.main.allSource
+}
+
+publishing {
+ publications {
+ javaLibrary(MavenPublication) {
+ artifactId 'mockito-kotlin'
+
+ from components.java
+
+ artifact sourceJar {
+ classifier "sources"
+ }
+
+ artifact javadocJar
+
+ pom.withXml {
+ def root = asNode()
+ root.appendNode('name', 'Mockito-Kotlin')
+ root.appendNode('description', 'Using Mockito with Kotlin.')
+ root.appendNode('url', 'https://github.com/mockito/mockito-kotlin')
+
+ def scm = root.appendNode('scm')
+ scm.appendNode('url', 'scm:git@github.com:mockito/mockito-kotlin.git')
+
+ def licenses = root.appendNode('licenses')
+ def mitLicense = licenses.appendNode('license')
+ mitLicense.appendNode('name', 'MIT')
+
+ def developers = root.appendNode('developers')
+ def nhaarman = developers.appendNode('developer')
+ nhaarman.appendNode('id', 'nhaarman')
+ nhaarman.appendNode('name', 'Niek Haarman')
+ }
+ }
+ }
+
+ //useful for testing - running "publish" will create artifacts/pom in a local dir
+ repositories { maven { url = "$rootProject.buildDir/repo" } }
+}
+
+clean {
+ delete "$rootProject.buildDir/repo"
+}
+
+// Avoid generation of the module metadata so that we don't have to publish an additional file
+// and keep the build logic simple.
+tasks.withType(GenerateModuleMetadata) {
+ enabled = false
+}
+
+//fleshes out problems with Maven pom generation when building
+tasks.build.dependsOn('publishJavaLibraryPublicationToMavenLocal')
+
+apply plugin: 'signing' //https://docs.gradle.org/current/userguide/signing_plugin.html
+signing {
+ if (System.getenv("PGP_KEY")) {
+ useInMemoryPgpKeys(System.getenv("PGP_KEY"), System.getenv("PGP_PWD"))
+ sign publishing.publications.javaLibrary
+ }
+}
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..e708b1c
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..28ff446
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.1-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
new file mode 100755
index 0000000..4f906e0
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,185 @@
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=`expr $i + 1`
+ done
+ case $i in
+ 0) set -- ;;
+ 1) set -- "$args0" ;;
+ 2) set -- "$args0" "$args1" ;;
+ 3) set -- "$args0" "$args1" "$args2" ;;
+ 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=`save "$@"`
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..ac1b06f
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/mockito-kotlin/build.gradle b/mockito-kotlin/build.gradle
new file mode 100644
index 0000000..6c726db
--- /dev/null
+++ b/mockito-kotlin/build.gradle
@@ -0,0 +1,49 @@
+apply plugin: 'kotlin'
+apply from: '../gradle/publishing.gradle'
+apply plugin: 'org.jetbrains.dokka'
+
+buildscript {
+ ext.kotlin_version = "1.3.50"
+
+ repositories {
+ mavenCentral()
+ jcenter()
+ }
+
+ dependencies {
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ classpath "org.jetbrains.dokka:dokka-gradle-plugin:0.9.17"
+ }
+}
+
+repositories {
+ mavenCentral()
+ jcenter()
+}
+
+dependencies {
+ compileOnly "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
+ compileOnly 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.0.0'
+
+ compile "org.mockito:mockito-core:2.23.0"
+
+ testCompile 'junit:junit:4.12'
+ testCompile 'com.nhaarman:expect.kt:1.0.0'
+
+ testCompile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
+ testCompile 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.0.0'
+
+ testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.0"
+}
+
+dokka {
+ outputFormat = 'html'
+ outputDirectory = "$buildDir/javadoc"
+
+ linkMapping {
+ dir = "src/main/kotlin"
+ url = "https://github.com/nhaarman/mockito-kotlin/tree/master/mockito-kotlin/src/main/kotlin"
+ suffix = "#L"
+ }
+}
+javadoc.dependsOn dokka
diff --git a/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/ArgumentCaptor.kt b/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/ArgumentCaptor.kt
new file mode 100644
index 0000000..253a58c
--- /dev/null
+++ b/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/ArgumentCaptor.kt
@@ -0,0 +1,212 @@
+/*
+ * The MIT License
+ *
+ * Copyright (c) 2018 Niek Haarman
+ * Copyright (c) 2007 Mockito contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package org.mockito.kotlin
+
+import org.mockito.kotlin.internal.createInstance
+import org.mockito.ArgumentCaptor
+import kotlin.reflect.KClass
+
+/**
+ * Creates a [KArgumentCaptor] for given type.
+ */
+inline fun <reified T : Any> argumentCaptor(): KArgumentCaptor<T> {
+ return KArgumentCaptor(ArgumentCaptor.forClass(T::class.java), T::class)
+}
+
+/**
+ * Creates 2 [KArgumentCaptor]s for given types.
+ */
+inline fun <reified A : Any, reified B : Any> argumentCaptor(
+ a: KClass<A> = A::class,
+ b: KClass<B> = B::class
+): Pair<KArgumentCaptor<A>, KArgumentCaptor<B>> {
+ return Pair(
+ KArgumentCaptor(ArgumentCaptor.forClass(a.java), a),
+ KArgumentCaptor(ArgumentCaptor.forClass(b.java), b)
+ )
+}
+
+/**
+ * Creates 3 [KArgumentCaptor]s for given types.
+ */
+inline fun <reified A : Any, reified B : Any, reified C : Any> argumentCaptor(
+ a: KClass<A> = A::class,
+ b: KClass<B> = B::class,
+ c: KClass<C> = C::class
+): Triple<KArgumentCaptor<A>, KArgumentCaptor<B>, KArgumentCaptor<C>> {
+ return Triple(
+ KArgumentCaptor(ArgumentCaptor.forClass(a.java), a),
+ KArgumentCaptor(ArgumentCaptor.forClass(b.java), b),
+ KArgumentCaptor(ArgumentCaptor.forClass(c.java), c)
+ )
+}
+
+class ArgumentCaptorHolder4<out A, out B, out C, out D>(
+ val first: A,
+ val second: B,
+ val third: C,
+ val fourth: D
+) {
+
+ operator fun component1() = first
+ operator fun component2() = second
+ operator fun component3() = third
+ operator fun component4() = fourth
+}
+
+class ArgumentCaptorHolder5<out A, out B, out C, out D, out E>(
+ val first: A,
+ val second: B,
+ val third: C,
+ val fourth: D,
+ val fifth: E
+) {
+
+ operator fun component1() = first
+ operator fun component2() = second
+ operator fun component3() = third
+ operator fun component4() = fourth
+ operator fun component5() = fifth
+}
+
+
+/**
+ * Creates 4 [KArgumentCaptor]s for given types.
+ */
+inline fun <reified A : Any, reified B : Any, reified C : Any, reified D : Any> argumentCaptor(
+ a: KClass<A> = A::class,
+ b: KClass<B> = B::class,
+ c: KClass<C> = C::class,
+ d: KClass<D> = D::class
+): ArgumentCaptorHolder4<KArgumentCaptor<A>, KArgumentCaptor<B>, KArgumentCaptor<C>, KArgumentCaptor<D>> {
+ return ArgumentCaptorHolder4(
+ KArgumentCaptor(ArgumentCaptor.forClass(a.java), a),
+ KArgumentCaptor(ArgumentCaptor.forClass(b.java), b),
+ KArgumentCaptor(ArgumentCaptor.forClass(c.java), c),
+ KArgumentCaptor(ArgumentCaptor.forClass(d.java), d)
+ )
+}
+
+/**
+ * Creates 4 [KArgumentCaptor]s for given types.
+ */
+inline fun <reified A : Any, reified B : Any, reified C : Any, reified D : Any, reified E : Any> argumentCaptor(
+ a: KClass<A> = A::class,
+ b: KClass<B> = B::class,
+ c: KClass<C> = C::class,
+ d: KClass<D> = D::class,
+ e: KClass<E> = E::class
+): ArgumentCaptorHolder5<KArgumentCaptor<A>, KArgumentCaptor<B>, KArgumentCaptor<C>, KArgumentCaptor<D>, KArgumentCaptor<E>> {
+ return ArgumentCaptorHolder5(
+ KArgumentCaptor(ArgumentCaptor.forClass(a.java), a),
+ KArgumentCaptor(ArgumentCaptor.forClass(b.java), b),
+ KArgumentCaptor(ArgumentCaptor.forClass(c.java), c),
+ KArgumentCaptor(ArgumentCaptor.forClass(d.java), d),
+ KArgumentCaptor(ArgumentCaptor.forClass(e.java), e)
+ )
+}
+
+/**
+ * Creates a [KArgumentCaptor] for given type, taking in a lambda to allow fast verification.
+ */
+inline fun <reified T : Any> argumentCaptor(f: KArgumentCaptor<T>.() -> Unit): KArgumentCaptor<T> {
+ return argumentCaptor<T>().apply(f)
+}
+
+/**
+ * Creates a [KArgumentCaptor] for given nullable type.
+ */
+inline fun <reified T : Any> nullableArgumentCaptor(): KArgumentCaptor<T?> {
+ return KArgumentCaptor(ArgumentCaptor.forClass(T::class.java), T::class)
+}
+
+/**
+ * Creates a [KArgumentCaptor] for given nullable type, taking in a lambda to allow fast verification.
+ */
+inline fun <reified T : Any> nullableArgumentCaptor(f: KArgumentCaptor<T?>.() -> Unit): KArgumentCaptor<T?> {
+ return nullableArgumentCaptor<T>().apply(f)
+}
+
+/**
+ * Alias for [ArgumentCaptor.capture].
+ */
+inline fun <reified T : Any> capture(captor: ArgumentCaptor<T>): T {
+ return captor.capture() ?: createInstance()
+}
+
+class KArgumentCaptor<out T : Any?>(
+ private val captor: ArgumentCaptor<T>,
+ private val tClass: KClass<*>
+) {
+
+ /**
+ * The first captured value of the argument.
+ * @throws IndexOutOfBoundsException if the value is not available.
+ */
+ val firstValue: T
+ get() = captor.firstValue
+
+ /**
+ * The second captured value of the argument.
+ * @throws IndexOutOfBoundsException if the value is not available.
+ */
+ val secondValue: T
+ get() = captor.secondValue
+
+ /**
+ * The third captured value of the argument.
+ * @throws IndexOutOfBoundsException if the value is not available.
+ */
+ val thirdValue: T
+ get() = captor.thirdValue
+
+ /**
+ * The last captured value of the argument.
+ * @throws IndexOutOfBoundsException if the value is not available.
+ */
+ val lastValue: T
+ get() = captor.lastValue
+
+ val allValues: List<T>
+ get() = captor.allValues
+
+ @Suppress("UNCHECKED_CAST")
+ fun capture(): T {
+ return captor.capture() ?: createInstance(tClass) as T
+ }
+}
+
+val <T> ArgumentCaptor<T>.firstValue: T
+ get() = allValues[0]
+
+val <T> ArgumentCaptor<T>.secondValue: T
+ get() = allValues[1]
+
+val <T> ArgumentCaptor<T>.thirdValue: T
+ get() = allValues[2]
+
+val <T> ArgumentCaptor<T>.lastValue: T
+ get() = allValues.last()
diff --git a/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/BDDMockito.kt b/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/BDDMockito.kt
new file mode 100644
index 0000000..867f4c1
--- /dev/null
+++ b/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/BDDMockito.kt
@@ -0,0 +1,81 @@
+/*
+ * The MIT License
+ *
+ * Copyright (c) 2018 Niek Haarman
+ * Copyright (c) 2007 Mockito contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package org.mockito.kotlin
+
+import org.mockito.BDDMockito
+import org.mockito.BDDMockito.BDDMyOngoingStubbing
+import org.mockito.invocation.InvocationOnMock
+import org.mockito.stubbing.Answer
+
+/**
+ * Alias for [BDDMockito.given].
+ */
+fun <T> given(methodCall: T): BDDMockito.BDDMyOngoingStubbing<T> {
+ return BDDMockito.given(methodCall)
+}
+
+/**
+ * Alias for [BDDMockito.given] with a lambda.
+ */
+fun <T> given(methodCall: () -> T): BDDMyOngoingStubbing<T> {
+ return given(methodCall())
+}
+
+/**
+ * Alias for [BDDMockito.then].
+ */
+fun <T> then(mock: T): BDDMockito.Then<T> {
+ return BDDMockito.then(mock)
+}
+
+/**
+ * Alias for [BDDMyOngoingStubbing.will]
+ * */
+infix fun <T> BDDMyOngoingStubbing<T>.will(value: Answer<T>): BDDMockito.BDDMyOngoingStubbing<T> {
+ return will(value)
+}
+
+/**
+ * Alias for [BBDMyOngoingStubbing.willAnswer], accepting a lambda.
+ */
+infix fun <T> BDDMyOngoingStubbing<T>.willAnswer(value: (InvocationOnMock) -> T?): BDDMockito.BDDMyOngoingStubbing<T> {
+ return willAnswer { value(it) }
+}
+
+/**
+ * Alias for [BBDMyOngoingStubbing.willReturn].
+ */
+infix fun <T> BDDMyOngoingStubbing<T>.willReturn(value: () -> T): BDDMockito.BDDMyOngoingStubbing<T> {
+ return willReturn(value())
+}
+
+/**
+ * Alias for [BBDMyOngoingStubbing.willThrow].
+ */
+infix fun <T> BDDMyOngoingStubbing<T>.willThrow(value: () -> Throwable): BDDMockito.BDDMyOngoingStubbing<T> {
+ return willThrow(value())
+}
+
diff --git a/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/KStubbing.kt b/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/KStubbing.kt
new file mode 100644
index 0000000..bbf36bf
--- /dev/null
+++ b/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/KStubbing.kt
@@ -0,0 +1,84 @@
+/*
+ * The MIT License
+ *
+ * Copyright (c) 2018 Niek Haarman
+ * Copyright (c) 2007 Mockito contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package org.mockito.kotlin
+
+import org.mockito.kotlin.internal.createInstance
+import kotlinx.coroutines.runBlocking
+import org.mockito.Mockito
+import org.mockito.stubbing.OngoingStubbing
+import kotlin.reflect.KClass
+
+
+inline fun <T> stubbing(
+ mock: T,
+ stubbing: KStubbing<T>.(T) -> Unit
+) {
+ KStubbing(mock).stubbing(mock)
+}
+
+inline fun <T : Any> T.stub(stubbing: KStubbing<T>.(T) -> Unit): T {
+ return apply { KStubbing(this).stubbing(this) }
+}
+
+class KStubbing<out T>(val mock: T) {
+
+ fun <R> on(methodCall: R): OngoingStubbing<R> = Mockito.`when`(methodCall)
+
+ fun <R : Any> onGeneric(methodCall: T.() -> R?, c: KClass<R>): OngoingStubbing<R> {
+ val r = try {
+ mock.methodCall()
+ } catch (e: NullPointerException) {
+ // An NPE may be thrown by the Kotlin type system when the MockMethodInterceptor returns a
+ // null value for a non-nullable generic type.
+ // We catch this NPE to return a valid instance.
+ // The Mockito state has already been modified at this point to reflect
+ // the wanted changes.
+ createInstance(c)
+ }
+ return Mockito.`when`(r)
+ }
+
+ inline fun <reified R : Any> onGeneric(noinline methodCall: T.() -> R?): OngoingStubbing<R> {
+ return onGeneric(methodCall, R::class)
+ }
+
+ fun <R> on(methodCall: T.() -> R): OngoingStubbing<R> {
+ return try {
+ Mockito.`when`(mock.methodCall())
+ } catch (e: NullPointerException) {
+ throw MockitoKotlinException(
+ "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.",
+ e
+ )
+ }
+ }
+
+ fun <T : Any, R> KStubbing<T>.onBlocking(
+ m: suspend T.() -> R
+ ): OngoingStubbing<R> {
+ return runBlocking { Mockito.`when`(mock.m()) }
+ }
+}
\ No newline at end of file
diff --git a/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/Matchers.kt b/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/Matchers.kt
new file mode 100644
index 0000000..a17da95
--- /dev/null
+++ b/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/Matchers.kt
@@ -0,0 +1,139 @@
+/*
+ * The MIT License
+ *
+ * Copyright (c) 2018 Niek Haarman
+ * Copyright (c) 2007 Mockito contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package org.mockito.kotlin
+
+import org.mockito.kotlin.internal.createInstance
+import org.mockito.ArgumentMatcher
+import org.mockito.Mockito
+
+/** Object argument that is equal to the given value. */
+fun <T> eq(value: T): T {
+ return Mockito.eq(value) ?: value
+}
+
+/** Object argument that is the same as the given value. */
+fun <T> same(value: T): T {
+ return Mockito.same(value) ?: value
+}
+
+/** Matches any object, excluding nulls. */
+inline fun <reified T : Any> any(): T {
+ return Mockito.any(T::class.java) ?: createInstance()
+}
+
+/** Matches anything, including nulls. */
+inline fun <reified T : Any> anyOrNull(): T {
+ return Mockito.any<T>() ?: createInstance()
+}
+
+/** Matches any vararg object, including nulls. */
+inline fun <reified T : Any> anyVararg(): T {
+ return Mockito.any<T>() ?: createInstance()
+}
+
+/** Matches any array of type T. */
+inline fun <reified T : Any?> anyArray(): Array<T> {
+ return Mockito.any(Array<T>::class.java) ?: arrayOf()
+}
+
+/**
+ * Creates a custom argument matcher.
+ * `null` values will never evaluate to `true`.
+ *
+ * @param predicate An extension function on [T] that returns `true` when a [T] matches the predicate.
+ */
+inline fun <reified T : Any> argThat(noinline predicate: T.() -> Boolean): T {
+ return Mockito.argThat { arg: T? -> arg?.predicate() ?: false } ?: createInstance(
+ T::class
+ )
+}
+
+/**
+ * Registers a custom ArgumentMatcher. The original Mockito function registers the matcher and returns null,
+ * here the required type is returned.
+ *
+ * @param matcher The ArgumentMatcher on [T] to be registered.
+ */
+inline fun <reified T : Any> argThat(matcher: ArgumentMatcher<T>): T {
+ return Mockito.argThat(matcher) ?: createInstance()
+}
+
+/**
+ * Alias for [argThat].
+ *
+ * Creates a custom argument matcher.
+ * `null` values will never evaluate to `true`.
+ *
+ * @param predicate An extension function on [T] that returns `true` when a [T] matches the predicate.
+ */
+inline fun <reified T : Any> argForWhich(noinline predicate: T.() -> Boolean): T {
+ return argThat(predicate)
+}
+
+/**
+ * Creates a custom argument matcher.
+ * `null` values will never evaluate to `true`.
+ *
+ * @param predicate A function that returns `true` when given [T] matches the predicate.
+ */
+inline fun <reified T : Any> argWhere(noinline predicate: (T) -> Boolean): T {
+ return argThat(predicate)
+}
+
+/**
+ * Argument that implements the given class.
+ */
+inline fun <reified T : Any> isA(): T {
+ return Mockito.isA(T::class.java) ?: createInstance()
+}
+
+/**
+ * `null` argument.
+ */
+fun <T : Any> isNull(): T? = Mockito.isNull()
+
+/**
+ * Not `null` argument.
+ */
+fun <T : Any> isNotNull(): T? {
+ return Mockito.isNotNull()
+}
+
+/**
+ * Not `null` argument.
+ */
+fun <T : Any> notNull(): T? {
+ return Mockito.notNull()
+}
+
+/**
+ * Object argument that is reflection-equal to the given value with support for excluding
+ * selected fields from a class.
+ */
+inline fun <reified T : Any> refEq(value: T, vararg excludeFields: String): T {
+ return Mockito.refEq<T>(value, *excludeFields) ?: createInstance()
+}
+
diff --git a/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/Mocking.kt b/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/Mocking.kt
new file mode 100644
index 0000000..9f6acd2
--- /dev/null
+++ b/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/Mocking.kt
@@ -0,0 +1,211 @@
+/*
+ * The MIT License
+ *
+ * Copyright (c) 2018 Niek Haarman
+ * Copyright (c) 2007 Mockito contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package org.mockito.kotlin
+
+import org.mockito.Incubating
+import org.mockito.MockSettings
+import org.mockito.Mockito
+import org.mockito.listeners.InvocationListener
+import org.mockito.mock.SerializableMode
+import org.mockito.stubbing.Answer
+import kotlin.DeprecationLevel.ERROR
+import kotlin.reflect.KClass
+
+/**
+ * Creates a mock for [T].
+ *
+ * @param extraInterfaces Specifies extra interfaces the mock should implement.
+ * @param name Specifies mock name. Naming mocks can be helpful for debugging - the name is used in all verification errors.
+ * @param spiedInstance Specifies the instance to spy on. Makes sense only for spies/partial mocks.
+ * @param defaultAnswer Specifies default answers to interactions.
+ * @param serializable Configures the mock to be serializable.
+ * @param serializableMode Configures the mock to be serializable with a specific serializable mode.
+ * @param verboseLogging Enables real-time logging of method invocations on this mock.
+ * @param invocationListeners Registers a listener for method invocations on this mock. The listener is notified every time a method on this mock is called.
+ * @param stubOnly A stub-only mock does not record method invocations, thus saving memory but disallowing verification of invocations.
+ * @param useConstructor Mockito attempts to use constructor when creating instance of the mock.
+ * @param outerInstance Makes it possible to mock non-static inner classes in conjunction with [useConstructor].
+ * @param lenient Lenient mocks bypass "strict stubbing" validation.
+ */
+inline fun <reified T : Any> mock(
+ extraInterfaces: Array<out KClass<out Any>>? = null,
+ name: String? = null,
+ spiedInstance: Any? = null,
+ defaultAnswer: Answer<Any>? = null,
+ serializable: Boolean = false,
+ serializableMode: SerializableMode? = null,
+ verboseLogging: Boolean = false,
+ invocationListeners: Array<InvocationListener>? = null,
+ stubOnly: Boolean = false,
+ @Incubating useConstructor: UseConstructor? = null,
+ @Incubating outerInstance: Any? = null,
+ @Incubating lenient: Boolean = false
+): T {
+ return Mockito.mock(
+ T::class.java,
+ withSettings(
+ extraInterfaces = extraInterfaces,
+ name = name,
+ spiedInstance = spiedInstance,
+ defaultAnswer = defaultAnswer,
+ serializable = serializable,
+ serializableMode = serializableMode,
+ verboseLogging = verboseLogging,
+ invocationListeners = invocationListeners,
+ stubOnly = stubOnly,
+ useConstructor = useConstructor,
+ outerInstance = outerInstance,
+ lenient = lenient
+ )
+ )!!
+}
+
+/**
+ * Creates a mock for [T], allowing for immediate stubbing.
+ *
+ * @param extraInterfaces Specifies extra interfaces the mock should implement.
+ * @param name Specifies mock name. Naming mocks can be helpful for debugging - the name is used in all verification errors.
+ * @param spiedInstance Specifies the instance to spy on. Makes sense only for spies/partial mocks.
+ * @param defaultAnswer Specifies default answers to interactions.
+ * @param serializable Configures the mock to be serializable.
+ * @param serializableMode Configures the mock to be serializable with a specific serializable mode.
+ * @param verboseLogging Enables real-time logging of method invocations on this mock.
+ * @param invocationListeners Registers a listener for method invocations on this mock. The listener is notified every time a method on this mock is called.
+ * @param stubOnly A stub-only mock does not record method invocations, thus saving memory but disallowing verification of invocations.
+ * @param useConstructor Mockito attempts to use constructor when creating instance of the mock.
+ * @param outerInstance Makes it possible to mock non-static inner classes in conjunction with [useConstructor].
+ * @param lenient Lenient mocks bypass "strict stubbing" validation.
+ */
+inline fun <reified T : Any> mock(
+ extraInterfaces: Array<out KClass<out Any>>? = null,
+ name: String? = null,
+ spiedInstance: Any? = null,
+ defaultAnswer: Answer<Any>? = null,
+ serializable: Boolean = false,
+ serializableMode: SerializableMode? = null,
+ verboseLogging: Boolean = false,
+ invocationListeners: Array<InvocationListener>? = null,
+ stubOnly: Boolean = false,
+ @Incubating useConstructor: UseConstructor? = null,
+ @Incubating outerInstance: Any? = null,
+ @Incubating lenient: Boolean = false,
+ stubbing: KStubbing<T>.(T) -> Unit
+): T {
+ return Mockito.mock(
+ T::class.java,
+ withSettings(
+ extraInterfaces = extraInterfaces,
+ name = name,
+ spiedInstance = spiedInstance,
+ defaultAnswer = defaultAnswer,
+ serializable = serializable,
+ serializableMode = serializableMode,
+ verboseLogging = verboseLogging,
+ invocationListeners = invocationListeners,
+ stubOnly = stubOnly,
+ useConstructor = useConstructor,
+ outerInstance = outerInstance,
+ lenient = lenient
+ )
+ ).apply { KStubbing(this).stubbing(this) }!!
+}
+
+/**
+ * Allows mock creation with additional mock settings.
+ * See [MockSettings].
+ *
+ * @param extraInterfaces Specifies extra interfaces the mock should implement.
+ * @param name Specifies mock name. Naming mocks can be helpful for debugging - the name is used in all verification errors.
+ * @param spiedInstance Specifies the instance to spy on. Makes sense only for spies/partial mocks.
+ * @param defaultAnswer Specifies default answers to interactions.
+ * @param serializable Configures the mock to be serializable.
+ * @param serializableMode Configures the mock to be serializable with a specific serializable mode.
+ * @param verboseLogging Enables real-time logging of method invocations on this mock.
+ * @param invocationListeners Registers a listener for method invocations on this mock. The listener is notified every time a method on this mock is called.
+ * @param stubOnly A stub-only mock does not record method invocations, thus saving memory but disallowing verification of invocations.
+ * @param useConstructor Mockito attempts to use constructor when creating instance of the mock.
+ * @param outerInstance Makes it possible to mock non-static inner classes in conjunction with [useConstructor].
+ * @param lenient Lenient mocks bypass "strict stubbing" validation.
+ */
+fun withSettings(
+ extraInterfaces: Array<out KClass<out Any>>? = null,
+ name: String? = null,
+ spiedInstance: Any? = null,
+ defaultAnswer: Answer<Any>? = null,
+ serializable: Boolean = false,
+ serializableMode: SerializableMode? = null,
+ verboseLogging: Boolean = false,
+ invocationListeners: Array<InvocationListener>? = null,
+ stubOnly: Boolean = false,
+ @Incubating useConstructor: UseConstructor? = null,
+ @Incubating outerInstance: Any? = null,
+ @Incubating lenient: Boolean = false
+): MockSettings = Mockito.withSettings().apply {
+ extraInterfaces?.let { extraInterfaces(*it.map { it.java }.toTypedArray()) }
+ name?.let { name(it) }
+ spiedInstance?.let { spiedInstance(it) }
+ defaultAnswer?.let { defaultAnswer(it) }
+ if (serializable) serializable()
+ serializableMode?.let { serializable(it) }
+ if (verboseLogging) verboseLogging()
+ invocationListeners?.let { invocationListeners(*it) }
+ if (stubOnly) stubOnly()
+ useConstructor?.let { useConstructor(*it.args) }
+ outerInstance?.let { outerInstance(it) }
+ if (lenient) lenient()
+}
+
+class UseConstructor private constructor(val args: Array<Any>) {
+
+ companion object {
+
+ /** Invokes the parameterless constructor. */
+ fun parameterless() = UseConstructor(emptyArray())
+
+ /** Invokes a constructor with given arguments. */
+ fun withArguments(vararg arguments: Any): UseConstructor {
+ return UseConstructor(arguments.asList().toTypedArray())
+ }
+ }
+}
+
+@Deprecated(
+ "Use mock() with optional arguments instead.",
+ ReplaceWith("mock<T>(defaultAnswer = a)"),
+ level = ERROR
+)
+inline fun <reified T : Any> mock(a: Answer<Any>): T = mock(defaultAnswer = a)
+
+@Deprecated(
+ "Use mock() with optional arguments instead.",
+ ReplaceWith("mock<T>(name = s)"),
+ level = ERROR
+)
+inline fun <reified T : Any> mock(s: String): T = mock(name = s)
+
+@Suppress("DeprecatedCallableAddReplaceWith")
+@Deprecated("Use mock() with optional arguments instead.", level = ERROR)
+inline fun <reified T : Any> mock(s: MockSettings): T = Mockito.mock(T::class.java, s)!!
\ No newline at end of file
diff --git a/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/Mockito.kt b/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/Mockito.kt
new file mode 100644
index 0000000..0f80e0c
--- /dev/null
+++ b/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/Mockito.kt
@@ -0,0 +1,41 @@
+/*
+ * The MIT License
+ *
+ * Copyright (c) 2018 Niek Haarman
+ * Copyright (c) 2007 Mockito contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package org.mockito.kotlin
+
+import org.mockito.MockingDetails
+import org.mockito.Mockito
+
+fun validateMockitoUsage() {
+ Mockito.validateMockitoUsage()
+}
+
+fun <T> reset(vararg mocks: T) {
+ Mockito.reset(*mocks)
+}
+
+fun mockingDetails(toInspect: Any): MockingDetails {
+ return Mockito.mockingDetails(toInspect)!!
+}
\ No newline at end of file
diff --git a/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/MockitoKotlinException.kt b/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/MockitoKotlinException.kt
new file mode 100644
index 0000000..3e209ae
--- /dev/null
+++ b/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/MockitoKotlinException.kt
@@ -0,0 +1,28 @@
+/*
+ * The MIT License
+ *
+ * Copyright (c) 2018 Niek Haarman
+ * Copyright (c) 2007 Mockito contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package org.mockito.kotlin
+
+class MockitoKotlinException(message: String?, cause: Throwable?) : RuntimeException(message, cause)
diff --git a/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/OngoingStubbing.kt b/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/OngoingStubbing.kt
new file mode 100644
index 0000000..3d97ce1
--- /dev/null
+++ b/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/OngoingStubbing.kt
@@ -0,0 +1,126 @@
+/*
+ * The MIT License
+ *
+ * Copyright (c) 2018 Niek Haarman
+ * Copyright (c) 2007 Mockito contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package org.mockito.kotlin
+
+import org.mockito.Mockito
+import org.mockito.invocation.InvocationOnMock
+import org.mockito.stubbing.Answer
+import org.mockito.stubbing.OngoingStubbing
+import kotlin.DeprecationLevel.ERROR
+import kotlin.reflect.KClass
+
+
+/**
+ * Enables stubbing methods. Use it when you want the mock to return particular value when particular method is called.
+ *
+ * Alias for [Mockito.when].
+ */
+@Suppress("NOTHING_TO_INLINE")
+inline fun <T> whenever(methodCall: T): OngoingStubbing<T> {
+ return Mockito.`when`(methodCall)!!
+}
+
+/**
+ * Sets a return value to be returned when the method is called.
+ *
+ * Alias for [OngoingStubbing.thenReturn].
+ */
+infix fun <T> OngoingStubbing<T>.doReturn(t: T): OngoingStubbing<T> {
+ return thenReturn(t)
+}
+
+/**
+ * Sets consecutive return values to be returned when the method is called.
+ *
+ * Alias for [OngoingStubbing.thenReturn].
+ */
+fun <T> OngoingStubbing<T>.doReturn(t: T, vararg ts: T): OngoingStubbing<T> {
+ return thenReturn(t, *ts)
+}
+
+/**
+ * Sets consecutive return values to be returned when the method is called.
+ */
+inline infix fun <reified T> OngoingStubbing<T>.doReturnConsecutively(ts: List<T>): OngoingStubbing<T> {
+ return thenReturn(
+ ts[0],
+ *ts.drop(1).toTypedArray()
+ )
+}
+
+/**
+ * Sets Throwable objects to be thrown when the method is called.
+ *
+ * Alias for [OngoingStubbing.thenThrow].
+ */
+infix fun <T> OngoingStubbing<T>.doThrow(t: Throwable): OngoingStubbing<T> {
+ return thenThrow(t)
+}
+
+/**
+ * Sets Throwable objects to be thrown when the method is called.
+ *
+ * Alias for [OngoingStubbing.doThrow].
+ */
+fun <T> OngoingStubbing<T>.doThrow(
+ t: Throwable,
+ vararg ts: Throwable
+): OngoingStubbing<T> {
+ return thenThrow(t, *ts)
+}
+
+/**
+ * Sets a Throwable type to be thrown when the method is called.
+ */
+infix fun <T> OngoingStubbing<T>.doThrow(t: KClass<out Throwable>): OngoingStubbing<T> {
+ return thenThrow(t.java)
+}
+
+/**
+ * Sets Throwable classes to be thrown when the method is called.
+ */
+fun <T> OngoingStubbing<T>.doThrow(
+ t: KClass<out Throwable>,
+ vararg ts: KClass<out Throwable>
+): OngoingStubbing<T> {
+ return thenThrow(t.java, *ts.map { it.java }.toTypedArray())
+}
+
+/**
+ * Sets a generic Answer for the method.
+ *
+ * Alias for [OngoingStubbing.thenAnswer].
+ */
+infix fun <T> OngoingStubbing<T>.doAnswer(answer: Answer<*>): OngoingStubbing<T> {
+ return thenAnswer(answer)
+}
+
+/**
+ * Sets a generic Answer for the method using a lambda.
+ */
+infix fun <T> OngoingStubbing<T>.doAnswer(answer: (InvocationOnMock) -> T?): OngoingStubbing<T> {
+ return thenAnswer(answer)
+}
diff --git a/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/Spying.kt b/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/Spying.kt
new file mode 100644
index 0000000..55fa9c0
--- /dev/null
+++ b/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/Spying.kt
@@ -0,0 +1,62 @@
+/*
+ * The MIT License
+ *
+ * Copyright (c) 2018 Niek Haarman
+ * Copyright (c) 2007 Mockito contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package org.mockito.kotlin
+
+import org.mockito.Mockito
+
+
+/**
+ * Creates a spy of the real object.
+ * The spy calls <b>real</b> methods unless they are stubbed.
+ */
+inline fun <reified T : Any> spy(): T {
+ return Mockito.spy(T::class.java)!!
+}
+
+/**
+ * Creates a spy of the real object, allowing for immediate stubbing.
+ * The spy calls <b>real</b> methods unless they are stubbed.
+ */
+inline fun <reified T : Any> spy(stubbing: KStubbing<T>.(T) -> Unit): T {
+ return Mockito.spy(T::class.java)
+ .apply { KStubbing(this).stubbing(this) }!!
+}
+
+/**
+ * Creates a spy of the real object. The spy calls <b>real</b> methods unless they are stubbed.
+ */
+fun <T> spy(value: T): T {
+ return Mockito.spy(value)!!
+}
+
+/**
+ * Creates a spy of the real object, allowing for immediate stubbing.
+ * The spy calls <b>real</b> methods unless they are stubbed.
+ */
+inline fun <reified T> spy(value: T, stubbing: KStubbing<T>.(T) -> Unit): T {
+ return spy(value)
+ .apply { KStubbing(this).stubbing(this) }!!
+}
\ No newline at end of file
diff --git a/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/Stubber.kt b/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/Stubber.kt
new file mode 100644
index 0000000..fb417fc
--- /dev/null
+++ b/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/Stubber.kt
@@ -0,0 +1,65 @@
+/*
+ * The MIT License
+ *
+ * Copyright (c) 2018 Niek Haarman
+ * Copyright (c) 2007 Mockito contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package org.mockito.kotlin
+
+import org.mockito.Mockito
+import org.mockito.invocation.InvocationOnMock
+import org.mockito.stubbing.Stubber
+import kotlin.reflect.KClass
+
+
+fun <T> doAnswer(answer: (InvocationOnMock) -> T?): Stubber {
+ return Mockito.doAnswer { answer(it) }!!
+}
+
+fun doCallRealMethod(): Stubber {
+ return Mockito.doCallRealMethod()!!
+}
+
+fun doNothing(): Stubber {
+ return Mockito.doNothing()!!
+}
+
+fun doReturn(value: Any?): Stubber {
+ return Mockito.doReturn(value)!!
+}
+
+fun doReturn(toBeReturned: Any?, vararg toBeReturnedNext: Any?): Stubber {
+ return Mockito.doReturn(
+ toBeReturned,
+ *toBeReturnedNext
+ )!!
+}
+
+fun doThrow(toBeThrown: KClass<out Throwable>): Stubber {
+ return Mockito.doThrow(toBeThrown.java)!!
+}
+
+fun doThrow(vararg toBeThrown: Throwable): Stubber {
+ return Mockito.doThrow(*toBeThrown)!!
+}
+
+fun <T> Stubber.whenever(mock: T) = `when`(mock)
\ No newline at end of file
diff --git a/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/Verification.kt b/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/Verification.kt
new file mode 100644
index 0000000..e79dd92
--- /dev/null
+++ b/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/Verification.kt
@@ -0,0 +1,263 @@
+/*
+ * The MIT License
+ *
+ * Copyright (c) 2018 Niek Haarman
+ * Copyright (c) 2007 Mockito contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package org.mockito.kotlin
+
+import org.mockito.kotlin.internal.createInstance
+import kotlinx.coroutines.runBlocking
+import org.mockito.InOrder
+import org.mockito.Mockito
+import org.mockito.verification.VerificationAfterDelay
+import org.mockito.verification.VerificationMode
+import org.mockito.verification.VerificationWithTimeout
+
+/**
+ * Verifies certain behavior <b>happened once</b>.
+ *
+ * Alias for [Mockito.verify].
+ */
+fun <T> verify(mock: T): T {
+ return Mockito.verify(mock)!!
+}
+
+/**
+ * Verifies certain suspending behavior <b>happened once</b>.
+ *
+ * Warning: Only one method call can be verified in the function.
+ * Subsequent method calls are ignored!
+ */
+fun <T> verifyBlocking(mock: T, f: suspend T.() -> Unit) {
+ val m = Mockito.verify(mock)
+ runBlocking { m.f() }
+}
+
+/**
+ * Verifies certain behavior happened at least once / exact number of times / never.
+ *
+ * Warning: Only one method call can be verified in the function.
+ * Subsequent method calls are ignored!
+ */
+fun <T> verifyBlocking(mock: T, mode: VerificationMode, f: suspend T.() -> Unit) {
+ val m = Mockito.verify(mock, mode)
+ runBlocking { m.f() }
+}
+/**
+ * Verifies certain behavior happened at least once / exact number of times / never.
+ *
+ * Alias for [Mockito.verify].
+ */
+fun <T> verify(mock: T, mode: VerificationMode): T {
+ return Mockito.verify(mock, mode)!!
+}
+
+/**
+ * Checks if any of given mocks has any unverified interaction.
+ *
+ * Alias for [Mockito.verifyNoMoreInteractions].
+ */
+fun <T> verifyNoMoreInteractions(vararg mocks: T) {
+ Mockito.verifyNoMoreInteractions(*mocks)
+}
+
+/**
+ * Verifies that no interactions happened on given mocks beyond the previously verified interactions.
+ *
+ * Alias for [Mockito.verifyZeroInteractions].
+ */
+fun verifyZeroInteractions(vararg mocks: Any) {
+ Mockito.verifyZeroInteractions(*mocks)
+}
+
+/**
+ * Allows verifying exact number of invocations.
+ *
+ * Alias for [Mockito.times].
+ */
+fun times(numInvocations: Int): VerificationMode {
+ return Mockito.times(numInvocations)!!
+}
+
+/**
+ * Allows at-least-x verification.
+ *
+ * Alias for [Mockito.atLeast].
+ */
+fun atLeast(numInvocations: Int): VerificationMode {
+ return Mockito.atLeast(numInvocations)!!
+}
+
+/**
+ * Allows at-least-once verification.
+ *
+ * Alias for [Mockito.atLeastOnce].
+ */
+fun atLeastOnce(): VerificationMode {
+ return Mockito.atLeastOnce()!!
+}
+
+/**
+ * Allows at-most-x verification.
+ *
+ * Alias for [Mockito.atMost].
+ */
+fun atMost(maxNumberOfInvocations: Int): VerificationMode {
+ return Mockito.atMost(maxNumberOfInvocations)!!
+}
+
+/**
+ * Allows non-greedy verification in order.
+ *
+ * Alias for [Mockito.calls].
+ */
+fun calls(wantedNumberOfInvocations: Int): VerificationMode {
+ return Mockito.calls(wantedNumberOfInvocations)!!
+}
+
+/**
+ * Alias for [times] with parameter `0`.
+ */
+fun never(): VerificationMode {
+ return Mockito.never()!!
+}
+
+/**
+ * Use this method in order to only clear invocations, when stubbing is non-trivial.
+ *
+ * Alias for [Mockito.clearInvocations].
+ */
+fun <T> clearInvocations(vararg mocks: T) {
+ Mockito.clearInvocations(*mocks)
+}
+
+/**
+ * Adds a description to be printed if verification fails.
+ *
+ * Alias for [Mockito.description].
+ */
+fun description(description: String): VerificationMode {
+ return Mockito.description(description)
+}
+
+/**
+ * Allows verifying over a given period. It causes a verify to wait for a specified period of time for a desired
+ * interaction rather than failing immediately if has not already happened. May be useful for testing in concurrent
+ * conditions.
+ */
+fun after(millis: Long): VerificationAfterDelay {
+ return Mockito.after(millis)!!
+}
+
+/**
+ * Allows verifying with timeout. It causes a verify to wait for a specified period of time for a desired
+ * interaction rather than fails immediately if has not already happened. May be useful for testing in concurrent
+ * conditions.
+ */
+fun timeout(millis: Long): VerificationWithTimeout {
+ return Mockito.timeout(millis)!!
+}
+
+/**
+ * Ignores stubbed methods of given mocks for the sake of verification.
+ *
+ * Alias for [Mockito.ignoreStubs].
+ */
+fun ignoreStubs(vararg mocks: Any): Array<out Any> {
+ return Mockito.ignoreStubs(*mocks)!!
+}
+
+/**
+ * Creates [InOrder] object that allows verifying mocks in order.
+ *
+ * Alias for [Mockito.inOrder].
+ */
+fun inOrder(vararg mocks: Any): InOrder {
+ return Mockito.inOrder(*mocks)!!
+}
+
+/**
+ * Creates [InOrder] object that allows verifying mocks in order.
+ * Accepts a lambda to allow easy evaluation.
+ *
+ * Alias for [Mockito.inOrder].
+ */
+inline fun inOrder(
+ vararg mocks: Any,
+ evaluation: InOrder.() -> Unit
+) {
+ Mockito.inOrder(*mocks).evaluation()
+}
+
+/**
+ * Allows [InOrder] verification for a single mocked instance:
+ *
+ * mock.inOrder {
+ * verify().foo()
+ * }
+ *
+ */
+inline fun <T> T.inOrder(block: InOrderOnType<T>.() -> Any) {
+ block.invoke(InOrderOnType(this))
+}
+
+class InOrderOnType<T>(private val t: T) : InOrder by inOrder(t as Any) {
+
+ fun verify(): T = verify(t)
+}
+
+/**
+ * Allows checking if given method was the only one invoked.
+ */
+fun only(): VerificationMode {
+ return Mockito.only()!!
+}
+
+
+/**
+ * For usage with verification only.
+ *
+ * For example:
+ * verify(myObject).doSomething(check { assertThat(it, is("Test")) })
+ *
+ * @param predicate A function that performs actions to verify an argument [T].
+ */
+inline fun <reified T : Any> check(noinline predicate: (T) -> Unit): T {
+ return Mockito.argThat { arg: T? ->
+ if (arg == null) error(
+ """The argument passed to the predicate was null.
+
+If you are trying to verify an argument to be null, use `isNull()`.
+If you are using `check` as part of a stubbing, use `argThat` or `argForWhich` instead.
+""".trimIndent()
+ )
+
+ try {
+ predicate(arg)
+ true
+ } catch (e: Error) {
+ e.printStackTrace()
+ false
+ }
+ } ?: createInstance(T::class)
+}
diff --git a/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/VerifyScope.kt b/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/VerifyScope.kt
new file mode 100644
index 0000000..72ac6e2
--- /dev/null
+++ b/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/VerifyScope.kt
@@ -0,0 +1,48 @@
+/*
+ * The MIT License
+ *
+ * Copyright (c) 2018 Niek Haarman
+ * Copyright (c) 2007 Mockito contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package org.mockito.kotlin
+
+
+/**
+ * Verify multiple calls on mock
+ * Supports an easier to read style of
+ *
+ * ```
+ * verify(mock) {
+ * 2 * { call() }
+ * }
+ * ```
+ */
+inline fun <T> verify(mock: T, block: VerifyScope<T>.() -> Unit) {
+ VerifyScope(mock).block()
+}
+
+class VerifyScope<out T>(val mock: T) {
+
+ operator inline fun Int.times(call: T.() -> Unit) {
+ verify(mock, org.mockito.kotlin.times(this)).call()
+ }
+}
\ No newline at end of file
diff --git a/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/internal/CreateInstance.kt b/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/internal/CreateInstance.kt
new file mode 100644
index 0000000..59ede91
--- /dev/null
+++ b/mockito-kotlin/src/main/kotlin/org/mockito/kotlin/internal/CreateInstance.kt
@@ -0,0 +1,56 @@
+/*
+ * The MIT License
+ *
+ * Copyright (c) 2018 Niek Haarman
+ * Copyright (c) 2007 Mockito contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package org.mockito.kotlin.internal
+
+import kotlin.reflect.KClass
+import java.lang.reflect.Array as JavaArray
+
+inline fun <reified T : Any> createInstance(): T {
+ return when (T::class) {
+ Boolean::class -> false as T
+ Byte::class -> 0.toByte() as T
+ Char::class -> 0.toChar() as T
+ Short::class -> 0.toShort() as T
+ Int::class -> 0 as T
+ Long::class -> 0L as T
+ Float::class -> 0f as T
+ Double::class -> 0.0 as T
+ else -> createInstance(T::class)
+ }
+}
+
+fun <T : Any> createInstance(kClass: KClass<T>): T {
+ return castNull()
+}
+
+/**
+ * Uses a quirk in the bytecode generated by Kotlin
+ * to cast [null] to a non-null type.
+ *
+ * See https://youtrack.jetbrains.com/issue/KT-8135.
+ */
+@Suppress("UNCHECKED_CAST")
+private fun <T> castNull(): T = null as T
diff --git a/mockito-kotlin/src/test/kotlin/test/CoroutinesTest.kt b/mockito-kotlin/src/test/kotlin/test/CoroutinesTest.kt
new file mode 100644
index 0000000..5ca6eb6
--- /dev/null
+++ b/mockito-kotlin/src/test/kotlin/test/CoroutinesTest.kt
@@ -0,0 +1,176 @@
+@file:Suppress("EXPERIMENTAL_FEATURE_WARNING")
+
+package test
+
+import com.nhaarman.expect.expect
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.withContext
+import org.junit.Test
+import org.mockito.kotlin.*
+
+
+class CoroutinesTest {
+
+ @Test
+ fun stubbingSuspending() {
+ /* Given */
+ val m = mock<SomeInterface> {
+ onBlocking { suspending() } doReturn 42
+ }
+
+ /* When */
+ val result = runBlocking { m.suspending() }
+
+ /* Then */
+ expect(result).toBe(42)
+ }
+
+ @Test
+ fun stubbingSuspending_usingSuspendingFunction() {
+ /* Given */
+ val m = mock<SomeInterface> {
+ onBlocking { suspending() } doReturn runBlocking { SomeClass().result(42) }
+ }
+
+ /* When */
+ val result = runBlocking { m.suspending() }
+
+ /* Then */
+ expect(result).toBe(42)
+ }
+
+ @Test
+ fun stubbingSuspending_runBlocking() = runBlocking {
+ /* Given */
+ val m = mock<SomeInterface> {
+ onBlocking { suspending() } doReturn 42
+ }
+
+ /* When */
+ val result = m.suspending()
+
+ /* Then */
+ expect(result).toBe(42)
+ }
+
+ @Test
+ fun stubbingNonSuspending() {
+ /* Given */
+ val m = mock<SomeInterface> {
+ onBlocking { nonsuspending() } doReturn 42
+ }
+
+ /* When */
+ val result = m.nonsuspending()
+
+ /* Then */
+ expect(result).toBe(42)
+ }
+
+ @Test
+ fun stubbingNonSuspending_runBlocking() = runBlocking {
+ /* Given */
+ val m = mock<SomeInterface> {
+ onBlocking { nonsuspending() } doReturn 42
+ }
+
+ /* When */
+ val result = m.nonsuspending()
+
+ /* Then */
+ expect(result).toBe(42)
+ }
+
+ @Test
+ fun delayingResult() {
+ /* Given */
+ val m = SomeClass()
+
+ /* When */
+ val result = runBlocking { m.delaying() }
+
+ /* Then */
+ expect(result).toBe(42)
+ }
+
+ @Test
+ fun delayingResult_runBlocking() = runBlocking {
+ /* Given */
+ val m = SomeClass()
+
+ /* When */
+ val result = m.delaying()
+
+ /* Then */
+ expect(result).toBe(42)
+ }
+
+ @Test
+ fun verifySuspendFunctionCalled() {
+ /* Given */
+ val m = mock<SomeInterface>()
+
+ /* When */
+ runBlocking { m.suspending() }
+
+ /* Then */
+ runBlocking { verify(m).suspending() }
+ }
+
+ @Test
+ fun verifySuspendFunctionCalled_runBlocking() = runBlocking<Unit> {
+ val m = mock<SomeInterface>()
+
+ m.suspending()
+
+ verify(m).suspending()
+ }
+
+ @Test
+ fun verifySuspendFunctionCalled_verifyBlocking() {
+ val m = mock<SomeInterface>()
+
+ runBlocking { m.suspending() }
+
+ verifyBlocking(m) { suspending() }
+ }
+
+ @Test
+ fun verifyAtLeastOnceSuspendFunctionCalled_verifyBlocking() {
+ val m = mock<SomeInterface>()
+
+ runBlocking { m.suspending() }
+ runBlocking { m.suspending() }
+
+ verifyBlocking(m, atLeastOnce()) { suspending() }
+ }
+
+ @Test
+ fun verifySuspendMethod() = runBlocking {
+ val testSubject: SomeInterface = mock()
+
+ testSubject.suspending()
+
+ inOrder(testSubject) {
+ verify(testSubject).suspending()
+ }
+ }
+}
+
+interface SomeInterface {
+
+ suspend fun suspending(): Int
+ fun nonsuspending(): Int
+}
+
+class SomeClass {
+
+ suspend fun result(r: Int) = withContext(Dispatchers.Default) { r }
+
+ suspend fun delaying() = withContext(Dispatchers.Default) {
+ delay(100)
+ 42
+ }
+}
diff --git a/ops/mockMakerInline.sh b/ops/mockMakerInline.sh
new file mode 100755
index 0000000..441b07d
--- /dev/null
+++ b/ops/mockMakerInline.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+set -ev
+
+if [ ${MOCK_MAKER} = "mock-maker-inline" ]; then
+ mkdir -p tests/src/test/resources/mockito-extensions
+ cp ops/org.mockito.plugins.MockMaker tests/src/test/resources/mockito-extensions/
+fi
+
+exit 0;
+
diff --git a/ops/org.mockito.plugins.MockMaker b/ops/org.mockito.plugins.MockMaker
new file mode 100644
index 0000000..ca6ee9c
--- /dev/null
+++ b/ops/org.mockito.plugins.MockMaker
@@ -0,0 +1 @@
+mock-maker-inline
\ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..5086f47
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,2 @@
+include 'mockito-kotlin'
+include 'tests'
\ No newline at end of file
diff --git a/tests/README.md b/tests/README.md
new file mode 100644
index 0000000..a29d680
--- /dev/null
+++ b/tests/README.md
@@ -0,0 +1,7 @@
+Mockito-Kotlin tests
+====================
+
+Tests should be placed in this module.
+CI is set up to execute tests for all major versions of Kotlin,
+whilst keeping the library version on the latest version.
+This ensures the library is backwards compatible for all Kotlin versions.
diff --git a/tests/build.gradle b/tests/build.gradle
new file mode 100644
index 0000000..24ab716
--- /dev/null
+++ b/tests/build.gradle
@@ -0,0 +1,29 @@
+buildscript {
+ ext.kotlin_version = System.getenv("KOTLIN_VERSION") ?: '1.3.50'
+ println "$project uses Kotlin $kotlin_version"
+
+ repositories {
+ mavenCentral()
+ }
+ dependencies {
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ }
+}
+
+apply plugin: 'java'
+apply plugin: 'kotlin'
+
+repositories {
+ mavenCentral()
+ jcenter()
+}
+
+dependencies {
+ compile files("${rootProject.projectDir}/mockito-kotlin/build/libs/mockito-kotlin-${version}.jar")
+
+ compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
+ compile "org.mockito:mockito-core:2.23.0"
+
+ testCompile "junit:junit:4.12"
+ testCompile "com.nhaarman:expect.kt:1.0.0"
+}
\ No newline at end of file
diff --git a/tests/src/test/kotlin/test/ArgumentCaptorTest.kt b/tests/src/test/kotlin/test/ArgumentCaptorTest.kt
new file mode 100644
index 0000000..703e750
--- /dev/null
+++ b/tests/src/test/kotlin/test/ArgumentCaptorTest.kt
@@ -0,0 +1,229 @@
+package test
+
+import com.nhaarman.expect.expect
+import com.nhaarman.expect.expectErrorWithMessage
+import org.junit.Test
+import org.mockito.kotlin.*
+import java.util.*
+
+class ArgumentCaptorTest : TestBase() {
+
+ @Test
+ fun argumentCaptor_withSingleValue() {
+ /* Given */
+ val date: Date = mock()
+
+ /* When */
+ date.time = 5L
+
+ /* Then */
+ val captor = argumentCaptor<Long>()
+ verify(date).time = captor.capture()
+ expect(captor.lastValue).toBe(5L)
+ }
+
+ @Test
+ fun argumentCaptor_destructuring2() {
+ /* Given */
+ val date: Date = mock()
+
+ /* When */
+ date.time = 5L
+
+ /* Then */
+ val (captor1, captor2) = argumentCaptor<Long, Long>()
+ verify(date).time = captor1.capture()
+ verify(date).time = captor2.capture()
+ expect(captor1.lastValue).toBe(5L)
+ expect(captor2.lastValue).toBe(5L)
+ }
+
+ @Test
+ fun argumentCaptor_destructuring3() {
+ /* Given */
+ val date: Date = mock()
+
+ /* When */
+ date.time = 5L
+
+ /* Then */
+ val (captor1, captor2, captor3) = argumentCaptor<Long, Long, Long>()
+ val verifyCaptor: KArgumentCaptor<Long>.() -> Unit = {
+ verify(date).time = capture()
+ expect(lastValue).toBe(5L)
+ }
+ captor1.apply(verifyCaptor)
+ captor2.apply(verifyCaptor)
+ captor3.apply(verifyCaptor)
+ }
+
+ @Test
+ fun argumentCaptor_destructuring4() {
+ /* Given */
+ val date: Date = mock()
+
+ /* When */
+ date.time = 5L
+
+ /* Then */
+ val (captor1, captor2, captor3, captor4) = argumentCaptor<Long, Long, Long, Long>()
+ val verifyCaptor: KArgumentCaptor<Long>.() -> Unit = {
+ verify(date).time = capture()
+ expect(lastValue).toBe(5L)
+ }
+ captor1.apply(verifyCaptor)
+ captor2.apply(verifyCaptor)
+ captor3.apply(verifyCaptor)
+ captor4.apply(verifyCaptor)
+ }
+
+ @Test
+ fun argumentCaptor_destructuring5() {
+ /* Given */
+ val date: Date = mock()
+
+ /* When */
+ date.time = 5L
+
+ /* Then */
+ val (captor1, captor2, captor3, captor4, captor5) = argumentCaptor<Long, Long, Long, Long, Long>()
+ val verifyCaptor: KArgumentCaptor<Long>.() -> Unit = {
+ verify(date).time = capture()
+ expect(lastValue).toBe(5L)
+ }
+ captor1.apply(verifyCaptor)
+ captor2.apply(verifyCaptor)
+ captor3.apply(verifyCaptor)
+ captor4.apply(verifyCaptor)
+ captor5.apply(verifyCaptor)
+ }
+
+ @Test
+ fun argumentCaptor_withNullValue_usingNonNullable() {
+ /* Given */
+ val m: Methods = mock()
+
+ /* When */
+ m.nullableString(null)
+
+ /* Then */
+ val captor = argumentCaptor<String>()
+ verify(m).nullableString(captor.capture())
+ expect(captor.lastValue).toBeNull()
+ }
+
+ @Test
+ fun argumentCaptor_withNullValue_usingNullable() {
+ /* Given */
+ val m: Methods = mock()
+
+ /* When */
+ m.nullableString(null)
+
+ /* Then */
+ val captor = nullableArgumentCaptor<String>()
+ verify(m).nullableString(captor.capture())
+ expect(captor.lastValue).toBeNull()
+ }
+
+ @Test
+ fun argumentCaptor_multipleValues() {
+ /* Given */
+ val date: Date = mock()
+
+ /* When */
+ date.time = 5L
+ date.time = 7L
+
+ /* Then */
+ val captor = argumentCaptor<Long>()
+ verify(date, times(2)).time = captor.capture()
+ expect(captor.allValues).toBe(listOf(5, 7))
+ }
+
+ @Test
+ fun argumentCaptor_multipleValuesIncludingNull() {
+ /* Given */
+ val m: Methods = mock()
+
+ /* When */
+ m.nullableString("test")
+ m.nullableString(null)
+
+ /* Then */
+ val captor = nullableArgumentCaptor<String>()
+ verify(m, times(2)).nullableString(captor.capture())
+ expect(captor.allValues).toBe(listOf("test", null))
+ }
+
+ @Test
+ fun argumentCaptor_callProperties() {
+ /* Given */
+ val m: Methods = mock()
+
+ /* When */
+ m.int(1)
+ m.int(2)
+ m.int(3)
+ m.int(4)
+ m.int(5)
+
+ /* Then */
+ argumentCaptor<Int>().apply {
+ verify(m, times(5)).int(capture())
+
+ expect(firstValue).toBe(1)
+ expect(secondValue).toBe(2)
+ expect(thirdValue).toBe(3)
+ expect(lastValue).toBe(5)
+ }
+ }
+
+ @Test(expected = IndexOutOfBoundsException::class)
+ fun argumentCaptor_callPropertyNotAvailable() {
+ /* Given */
+ val m: Methods = mock()
+
+ /* When */
+ m.int(1)
+
+ /* Then */
+ argumentCaptor<Int>().apply {
+ verify(m).int(capture())
+
+ expect(secondValue).toBe(2)
+ }
+ }
+
+ @Test
+ fun argumentCaptor_withSingleValue_lambda() {
+ /* Given */
+ val date: Date = mock()
+
+ /* When */
+ date.time = 5L
+
+ /* Then */
+ argumentCaptor<Long> {
+ verify(date).time = capture()
+ expect(lastValue).toBe(5L)
+ }
+ }
+
+ @Test
+ fun argumentCaptor_withSingleValue_lambda_properlyFails() {
+ /* Given */
+ val date: Date = mock()
+
+ /* When */
+ date.time = 5L
+
+ /* Then */
+ expectErrorWithMessage("Expected: 3 but was: 5") on {
+ argumentCaptor<Long> {
+ verify(date).time = capture()
+ expect(lastValue).toBe(3L)
+ }
+ }
+ }
+}
diff --git a/tests/src/test/kotlin/test/BDDMockitoTest.kt b/tests/src/test/kotlin/test/BDDMockitoTest.kt
new file mode 100644
index 0000000..0472163
--- /dev/null
+++ b/tests/src/test/kotlin/test/BDDMockitoTest.kt
@@ -0,0 +1,131 @@
+package test
+
+import com.nhaarman.expect.expect
+import org.junit.Test
+import org.mockito.kotlin.*
+import org.mockito.stubbing.Answer
+
+class BDDMockitoTest {
+
+ @Test
+ fun given_will_properlyStubs() {
+ /* Given */
+ val mock = mock<Methods>()
+
+ /* When */
+ given(mock.stringResult()) will Answer<String> { "Test" }
+
+ /* Then */
+ expect(mock.stringResult()).toBe("Test")
+ }
+
+ @Test
+ fun given_willReturn_properlyStubs() {
+ /* Given */
+ val mock = mock<Methods>()
+
+ /* When */
+ given(mock.stringResult()).willReturn("Test")
+
+ /* Then */
+ expect(mock.stringResult()).toBe("Test")
+ }
+
+ @Test
+ fun givenLambda_willReturn_properlyStubs() {
+ /* Given */
+ val mock = mock<Methods>()
+
+ /* When */
+ given { mock.stringResult() }.willReturn("Test")
+
+ /* Then */
+ expect(mock.stringResult()).toBe("Test")
+ }
+
+ @Test
+ fun given_willReturnLambda_properlyStubs() {
+ /* Given */
+ val mock = mock<Methods>()
+
+ /* When */
+ given(mock.stringResult()).willReturn { "Test" }
+
+ /* Then */
+ expect(mock.stringResult()).toBe("Test")
+ }
+
+ @Test
+ fun givenLambda_willReturnLambda_properlyStubs() {
+ /* Given */
+ val mock = mock<Methods>()
+
+ /* When */
+ given { mock.stringResult() } willReturn { "Test" }
+
+ /* Then */
+ expect(mock.stringResult()).toBe("Test")
+ }
+
+ @Test
+ fun given_willAnswer_properlyStubs() {
+ /* Given */
+ val mock = mock<Methods>()
+
+ /* When */
+ given(mock.stringResult()).willAnswer { "Test" }
+
+ /* Then */
+ expect(mock.stringResult()).toBe("Test")
+ }
+
+ @Test
+ fun given_willAnswerInfix_properlyStubs() {
+ /* Given */
+ val mock = mock<Methods>()
+
+ /* When */
+ given(mock.stringResult()) willAnswer { "Test" }
+
+ /* Then */
+ expect(mock.stringResult()).toBe("Test")
+ }
+
+ @Test
+ fun given_willAnswerInfix_withInvocationInfo_properlyStubs() {
+ /* Given */
+ val mock = mock<Methods>()
+
+ /* When */
+ given(mock.stringResult(any())) willAnswer { invocation ->
+ (invocation.arguments[0] as String)
+ .reversed()
+ }
+
+ /* Then */
+ expect(mock.stringResult("Test")).toBe("tseT")
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun given_willThrowInfix_properlyStubs() {
+ /* Given */
+ val mock = mock<Methods>()
+
+ /* When */
+ given(mock.stringResult()) willThrow { IllegalStateException() }
+ mock.stringResult()
+ }
+
+ @Test
+ fun then() {
+ /* Given */
+ val mock = mock<Methods>()
+ whenever(mock.stringResult()).thenReturn("Test")
+
+ /* When */
+ mock.stringResult()
+
+ /* Then */
+ org.mockito.kotlin.then(mock).should().stringResult()
+ }
+}
diff --git a/tests/src/test/kotlin/test/Classes.kt b/tests/src/test/kotlin/test/Classes.kt
new file mode 100644
index 0000000..87b758d
--- /dev/null
+++ b/tests/src/test/kotlin/test/Classes.kt
@@ -0,0 +1,108 @@
+package test
+
+/*
+* The MIT License
+*
+* Copyright (c) 2016 Niek Haarman
+* Copyright (c) 2007 Mockito contributors
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*/
+
+open class Open {
+ open fun go(vararg arg: Any?) {
+ }
+
+ open fun modifiesContents(a: IntArray) {
+ for (i in 0..a.size - 1) {
+ a[i] = a[i] + 1
+ }
+ }
+
+ open fun stringResult() = "Default"
+
+ fun throwsNPE(): Any = throw NullPointerException("Test")
+}
+
+class Closed
+
+interface Methods {
+
+ fun intArray(i: IntArray)
+ fun closed(c: Closed)
+ fun closedArray(a: Array<Closed>)
+ fun closedNullableArray(a: Array<Closed?>)
+ fun closedCollection(c: Collection<Closed>)
+ fun closedList(c: List<Closed>)
+ fun closedStringMap(m: Map<Closed, String>)
+ fun closedSet(s: Set<Closed>)
+ fun string(s: String)
+ fun boolean(b: Boolean)
+ fun byte(b: Byte)
+ fun char(c: Char)
+ fun short(s: Short)
+ fun int(i: Int)
+ fun long(l: Long)
+ fun float(f: Float)
+ fun double(d: Double)
+ fun closedVararg(vararg c: Closed)
+ fun throwableClass(t: ThrowableClass)
+ fun nullableString(s: String?)
+
+ fun stringResult(): String
+ fun stringResult(s: String): String
+ fun nullableStringResult(): String?
+ fun builderMethod(): Methods
+ fun varargBooleanResult(vararg values: String): Boolean
+
+ fun nonDefaultReturnType(): ExtraInterface
+}
+
+interface ExtraInterface
+
+abstract class ThrowingConstructor {
+
+ constructor() {
+ error("Error in constructor")
+ }
+}
+
+abstract class ThrowingConstructorWithArgument {
+
+ constructor(s: String) {
+ error("Error in constructor: $s")
+ }
+}
+
+abstract class NonThrowingConstructorWithArgument {
+
+ constructor() {
+ error("Error in constructor")
+ }
+
+ @Suppress("UNUSED_PARAMETER")
+ constructor(s: String)
+}
+
+interface GenericMethods<T> {
+ fun genericMethod(): T
+ fun nullableReturnType(): T?
+}
+
+class ThrowableClass(cause: Throwable) : Throwable(cause)
diff --git a/tests/src/test/kotlin/test/EqTest.kt b/tests/src/test/kotlin/test/EqTest.kt
new file mode 100644
index 0000000..2f64c09
--- /dev/null
+++ b/tests/src/test/kotlin/test/EqTest.kt
@@ -0,0 +1,101 @@
+package test
+
+/*
+ * The MIT License
+ *
+ * Copyright (c) 2016 Niek Haarman
+ * Copyright (c) 2007 Mockito contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+import com.nhaarman.expect.expect
+import org.mockito.kotlin.eq
+import org.mockito.kotlin.mock
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.mockito.Mockito
+
+class EqTest : TestBase() {
+
+ private val interfaceInstance: MyInterface = MyClass()
+ private val openClassInstance: MyClass = MyClass()
+ private val closedClassInstance: ClosedClass = ClosedClass()
+
+ private lateinit var doAnswer: Open
+
+ @Before
+ fun setup() {
+ /* Create a proper Mockito state */
+ doAnswer = Mockito.doAnswer { }.`when`(mock())
+ }
+
+ @After
+ override fun tearDown() {
+ super.tearDown()
+
+ /* Close `any` Mockito state */
+ doAnswer.go(0)
+ }
+
+ @Test
+ fun eqInterfaceInstance() {
+ /* When */
+ val result = eq(interfaceInstance)
+
+ /* Then */
+ expect(result).toNotBeNull()
+ }
+
+ @Test
+ fun eqOpenClassInstance() {
+ /* When */
+ val result = eq(openClassInstance)
+
+ /* Then */
+ expect(result).toNotBeNull()
+ }
+
+ @Test
+ fun eqClosedClassInstance() {
+ /* When */
+ val result = eq(closedClassInstance)
+
+ /* Then */
+ expect(result).toNotBeNull()
+ }
+
+ @Test
+ fun nullArgument() {
+ /* Given */
+ val s: String? = null
+
+ /* When */
+ val result = eq(s)
+
+ /* Then */
+ expect(result).toBeNull()
+ }
+
+ private interface MyInterface
+ private open class MyClass : MyInterface
+ class ClosedClass
+}
+
diff --git a/tests/src/test/kotlin/test/MatchersTest.kt b/tests/src/test/kotlin/test/MatchersTest.kt
new file mode 100644
index 0000000..afed69f
--- /dev/null
+++ b/tests/src/test/kotlin/test/MatchersTest.kt
@@ -0,0 +1,334 @@
+package test
+
+import com.nhaarman.expect.expect
+import com.nhaarman.expect.expectErrorWithMessage
+import org.junit.Test
+import org.mockito.ArgumentMatcher
+import org.mockito.internal.matchers.VarargMatcher
+import org.mockito.invocation.InvocationOnMock
+import org.mockito.kotlin.*
+import org.mockito.stubbing.Answer
+import java.io.IOException
+import kotlin.check
+
+class MatchersTest : TestBase() {
+
+ @Test
+ fun anyString() {
+ mock<Methods>().apply {
+ string("")
+ verify(this).string(any())
+ }
+ }
+
+ @Test
+ fun anyInt() {
+ mock<Methods>().apply {
+ int(3)
+ verify(this).int(any())
+ }
+ }
+
+ @Test
+ fun anyClosedClass() {
+ mock<Methods>().apply {
+ closed(Closed())
+ verify(this).closed(any())
+ }
+ }
+
+ @Test
+ fun anyIntArray() {
+ mock<Methods>().apply {
+ intArray(intArrayOf())
+ verify(this).intArray(any())
+ }
+ }
+
+ @Test
+ fun anyClassArray() {
+ mock<Methods>().apply {
+ closedArray(arrayOf(Closed()))
+ verify(this).closedArray(anyArray())
+ }
+ }
+
+ @Test
+ fun anyNullableClassArray() {
+ mock<Methods>().apply {
+ closedNullableArray(arrayOf(Closed(), null))
+ verify(this).closedNullableArray(anyArray())
+ }
+ }
+
+ @Test
+ fun anyStringVararg() {
+ mock<Methods>().apply {
+ closedVararg(Closed(), Closed())
+ verify(this).closedVararg(anyVararg())
+ }
+ }
+
+ @Test
+ fun anyNull_neverVerifiesAny() {
+ mock<Methods>().apply {
+ nullableString(null)
+ verify(this, never()).nullableString(any())
+ }
+ }
+
+ @Test
+ fun anyNull_verifiesAnyOrNull() {
+ mock<Methods>().apply {
+ nullableString(null)
+ verify(this).nullableString(anyOrNull())
+ }
+ }
+
+ @Test
+ fun anyNull_forPrimitiveBoolean() {
+ mock<Methods>().apply {
+ boolean(false)
+ verify(this).boolean(anyOrNull())
+ }
+ }
+ @Test
+ fun anyNull_forPrimitiveByte() {
+ mock<Methods>().apply {
+ byte(3)
+ verify(this).byte(anyOrNull())
+ }
+ }
+
+ @Test
+ fun anyNull_forPrimitiveChar() {
+ mock<Methods>().apply {
+ char('a')
+ verify(this).char(anyOrNull())
+ }
+ }
+
+ @Test
+ fun anyNull_forPrimitiveShort() {
+ mock<Methods>().apply {
+ short(3)
+ verify(this).short(anyOrNull())
+ }
+ }
+
+ @Test
+ fun anyNull_forPrimitiveInt() {
+ mock<Methods>().apply {
+ int(3)
+ verify(this).int(anyOrNull())
+ }
+ }
+
+ @Test
+ fun anyNull_forPrimitiveLong() {
+ mock<Methods>().apply {
+ long(3)
+ verify(this).long(anyOrNull())
+ }
+ }
+
+ @Test
+ fun anyNull_forPrimitiveFloat() {
+ mock<Methods>().apply {
+ float(3f)
+ verify(this).float(anyOrNull())
+ }
+ }
+
+ @Test
+ fun anyNull_forPrimitiveDouble() {
+ mock<Methods>().apply {
+ double(3.0)
+ verify(this).double(anyOrNull())
+ }
+ }
+
+ /** https://github.com/nhaarman/mockito-kotlin/issues/27 */
+ @Test
+ fun anyThrowableWithSingleThrowableConstructor() {
+ mock<Methods>().apply {
+ throwableClass(ThrowableClass(IOException()))
+ verify(this).throwableClass(any())
+ }
+ }
+
+ @Test
+ fun listArgThat() {
+ mock<Methods>().apply {
+ closedList(listOf(Closed(), Closed()))
+ verify(this).closedList(
+ argThat {
+ size == 2
+ }
+ )
+ }
+ }
+
+ @Test
+ fun listArgForWhich() {
+ mock<Methods>().apply {
+ closedList(listOf(Closed(), Closed()))
+ verify(this).closedList(
+ argForWhich {
+ size == 2
+ }
+ )
+ }
+ }
+
+ @Test
+ fun listArgWhere() {
+ mock<Methods>().apply {
+ closedList(listOf(Closed(), Closed()))
+ verify(this).closedList(
+ argWhere {
+ it.size == 2
+ }
+ )
+ }
+ }
+
+ @Test
+ fun listArgCheck() {
+ mock<Methods>().apply {
+ closedList(listOf(Closed(), Closed()))
+ verify(this).closedList(
+ check {
+ expect(it.size).toBe(2)
+ }
+ )
+ }
+ }
+
+ @Test
+ fun checkProperlyFails() {
+ mock<Methods>().apply {
+ closedList(listOf(Closed(), Closed()))
+
+ expectErrorWithMessage("Argument(s) are different!") on {
+ verify(this).closedList(
+ check {
+ expect(it.size).toBe(1)
+ }
+ )
+ }
+ }
+ }
+
+ @Test
+ fun checkWithNullArgument_throwsError() {
+ mock<Methods>().apply {
+ nullableString(null)
+
+ expectErrorWithMessage("null").on {
+ verify(this).nullableString(check {})
+ }
+ }
+ }
+
+
+ @Test
+ fun isA_withNonNullableString() {
+ mock<Methods>().apply {
+ string("")
+ verify(this).string(isA<String>())
+ }
+ }
+
+ @Test
+ fun isA_withNullableString() {
+ mock<Methods>().apply {
+ nullableString("")
+ verify(this).nullableString(isA<String>())
+ }
+ }
+
+ @Test
+ fun same_withNonNullArgument() {
+ mock<Methods>().apply {
+ string("")
+ verify(this).string(same(""))
+ }
+ }
+
+ @Test
+ fun same_withNullableNonNullArgument() {
+ mock<Methods>().apply {
+ nullableString("")
+ verify(this).nullableString(same(""))
+ }
+ }
+
+ @Test
+ fun same_withNullArgument() {
+ mock<Methods>().apply {
+ nullableString(null)
+ verify(this).nullableString(same(null))
+ }
+ }
+
+ @Test
+ fun testVarargAnySuccess() {
+ /* Given */
+ val t = mock<Methods>()
+ // a matcher to check if any of the varargs was equals to "b"
+ val matcher = VarargAnyMatcher<String, Boolean>({ "b" == it }, true, false)
+
+ /* When */
+ whenever(t.varargBooleanResult(argThat(matcher))).thenAnswer(matcher)
+
+ /* Then */
+ expect(t.varargBooleanResult("a", "b", "c")).toBe(true)
+ }
+
+ @Test
+ fun testVarargAnyFail() {
+ /* Given */
+ val t = mock<Methods>()
+ // a matcher to check if any of the varargs was equals to "d"
+ val matcher = VarargAnyMatcher<String, Boolean>({ "d" == it }, true, false)
+
+ /* When */
+ whenever(t.varargBooleanResult(argThat(matcher))).thenAnswer(matcher)
+
+ /* Then */
+ expect(t.varargBooleanResult("a", "b", "c")).toBe(false)
+ }
+
+ /** https://github.com/nhaarman/mockito-kotlin/issues/328 */
+ @Test
+ fun testRefEqForNonNullableParameter() {
+ mock<Methods>().apply {
+ /* When */
+ val array = intArrayOf(2, 3)
+ intArray(array)
+
+ /* Then */
+ verify(this).intArray(refEq(array))
+ }
+ }
+
+ /**
+ * a VarargMatcher implementation for varargs of type [T] that will answer with type [R] if any of the var args
+ * matched. Needs to keep state between matching invocations.
+ */
+ private class VarargAnyMatcher<T, R>(
+ private val match: ((T) -> Boolean),
+ private val success: R,
+ private val failure: R
+ ) : ArgumentMatcher<T>, VarargMatcher, Answer<R> {
+ private var anyMatched = false
+
+ override fun matches(t: T): Boolean {
+ anyMatched = anyMatched or match(t)
+ return true
+ }
+
+ override fun answer(i: InvocationOnMock) = if (anyMatched) success else failure
+ }
+}
\ No newline at end of file
diff --git a/tests/src/test/kotlin/test/MockMaker.kt b/tests/src/test/kotlin/test/MockMaker.kt
new file mode 100644
index 0000000..54f3d91
--- /dev/null
+++ b/tests/src/test/kotlin/test/MockMaker.kt
@@ -0,0 +1,10 @@
+package test
+
+import org.mockito.internal.configuration.plugins.Plugins
+import org.mockito.internal.creation.bytebuddy.InlineByteBuddyMockMaker
+
+
+internal var mockMakerInlineEnabled: Boolean? = null
+internal fun mockMakerInlineEnabled(): Boolean {
+ return mockMakerInlineEnabled ?: (Plugins.getMockMaker() is InlineByteBuddyMockMaker)
+}
diff --git a/tests/src/test/kotlin/test/MockingTest.kt b/tests/src/test/kotlin/test/MockingTest.kt
new file mode 100644
index 0000000..43e6413
--- /dev/null
+++ b/tests/src/test/kotlin/test/MockingTest.kt
@@ -0,0 +1,357 @@
+package test
+
+import com.nhaarman.expect.expect
+import com.nhaarman.expect.expectErrorWithMessage
+import com.nhaarman.expect.fail
+import org.mockito.kotlin.UseConstructor.Companion.parameterless
+import org.mockito.kotlin.UseConstructor.Companion.withArguments
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.whenever
+import org.junit.Test
+import org.mockito.Mockito
+import org.mockito.exceptions.verification.WantedButNotInvoked
+import org.mockito.listeners.InvocationListener
+import org.mockito.mock.SerializableMode.BASIC
+import java.io.PrintStream
+import java.io.Serializable
+import java.util.*
+
+class MockingTest : TestBase() {
+
+ private lateinit var propertyInterfaceVariable: MyInterface
+ private lateinit var propertyClassVariable: MyClass
+
+ @Test
+ fun localInterfaceValue() {
+ /* When */
+ val instance: MyInterface = mock()
+
+ /* Then */
+ expect(instance).toNotBeNull()
+ }
+
+ @Test
+ fun propertyInterfaceVariable() {
+ /* When */
+ propertyInterfaceVariable = mock()
+
+ /* Then */
+ expect(propertyInterfaceVariable).toNotBeNull()
+ }
+
+ @Test
+ fun localClassValue() {
+ /* When */
+ val instance: MyClass = mock()
+
+ /* Then */
+ expect(instance).toNotBeNull()
+ }
+
+ @Test
+ fun propertyClassVariable() {
+ /* When */
+ propertyClassVariable = mock()
+
+ /* Then */
+ expect(propertyClassVariable).toNotBeNull()
+ }
+
+ @Test
+ fun untypedVariable() {
+ /* When */
+ val instance = mock<MyClass>()
+
+ expect(instance).toNotBeNull()
+ }
+
+ @Test
+ fun deepStubs() {
+ val cal: Calendar = mock(defaultAnswer = Mockito.RETURNS_DEEP_STUBS)
+ whenever(cal.time.time).thenReturn(123L)
+ expect(cal.time.time).toBe(123L)
+ }
+
+
+ @Test
+ fun testMockStubbing_lambda() {
+ /* Given */
+ val mock = mock<Open>() {
+ on { stringResult() } doReturn "A"
+ }
+
+ /* When */
+ val result = mock.stringResult()
+
+ /* Then */
+ expect(result).toBe("A")
+ }
+
+ @Test
+ fun testMockStubbing_normalOverridesLambda() {
+ /* Given */
+ val mock = mock<Open>() {
+ on { stringResult() }.doReturn("A")
+ }
+ whenever(mock.stringResult()).thenReturn("B")
+
+ /* When */
+ val result = mock.stringResult()
+
+ /* Then */
+ expect(result).toBe("B")
+ }
+
+
+ @Test
+ fun mock_withCustomDefaultAnswer_parameterName() {
+ /* Given */
+ val mock = mock<Methods>(defaultAnswer = Mockito.RETURNS_SELF)
+
+ /* When */
+ val result = mock.builderMethod()
+
+ /* Then */
+ expect(result).toBe(mock)
+ }
+
+ @Test
+ fun mock_withSettingsAPI_extraInterfaces() {
+ /* Given */
+ val mock = mock<Methods>(
+ extraInterfaces = arrayOf(ExtraInterface::class)
+ )
+
+ /* Then */
+ expect(mock).toBeInstanceOf<ExtraInterface>()
+ }
+
+ @Test
+ fun mock_withSettingsAPI_name() {
+ /* Given */
+ val mock = mock<Methods>(name = "myName")
+
+ /* When */
+ expectErrorWithMessage("myName.stringResult()") on {
+ verify(mock).stringResult()
+ }
+ }
+
+ @Test
+ fun mock_withSettingsAPI_defaultAnswer() {
+ /* Given */
+ val mock = mock<Methods>(defaultAnswer = Mockito.RETURNS_MOCKS)
+
+ /* When */
+ val result = mock.nonDefaultReturnType()
+
+ /* Then */
+ expect(result).toNotBeNull()
+ }
+
+ @Test
+ fun mock_withSettingsAPI_serializable() {
+ /* Given */
+ val mock = mock<Methods>(serializable = true)
+
+ /* Then */
+ expect(mock).toBeInstanceOf<Serializable>()
+ }
+
+ @Test
+ fun mock_withSettingsAPI_serializableMode() {
+ /* Given */
+ val mock = mock<Methods>(serializableMode = BASIC)
+
+ /* Then */
+ expect(mock).toBeInstanceOf<Serializable>()
+ }
+
+ @Test
+ fun mock_withSettingsAPI_verboseLogging() {
+ /* Given */
+ val out = mock<PrintStream>()
+ System.setOut(out)
+ val mock = mock<Methods>(verboseLogging = true)
+
+ try {
+ /* When */
+ verify(mock).stringResult()
+ fail("Expected an exception")
+ } catch (e: WantedButNotInvoked) {
+ /* Then */
+ verify(out).println("methods.stringResult();")
+ }
+ }
+
+ @Test
+ fun mock_withSettingsAPI_invocationListeners() {
+ /* Given */
+ var bool = false
+ val mock = mock<Methods>(invocationListeners = arrayOf(InvocationListener { bool = true }))
+
+ /* When */
+ mock.stringResult()
+
+ /* Then */
+ expect(bool).toHold()
+ }
+
+ @Test
+ fun mock_withSettingsAPI_stubOnly() {
+ /* Given */
+ val mock = mock<Methods>(stubOnly = true)
+
+ /* Expect */
+ expectErrorWithMessage("is a stubOnly() mock") on {
+
+ /* When */
+ verify(mock).stringResult()
+ }
+ }
+
+ @Test
+ fun mock_withSettingsAPI_useConstructor() {
+ /* Given */
+ expectErrorWithMessage("Unable to create mock instance of type ") on {
+ mock<ThrowingConstructor>(useConstructor = parameterless()) {}
+ }
+ }
+
+ @Test
+ fun mock_withSettingsAPI_useConstructorWithArguments_failing() {
+ /* Given */
+ expectErrorWithMessage("Unable to create mock instance of type ") on {
+ mock<ThrowingConstructorWithArgument>(useConstructor = withArguments("Test")) {}
+ }
+ }
+
+ @Test
+ fun mock_withSettingsAPI_useConstructorWithArguments() {
+ /* When */
+ val result = mock<NonThrowingConstructorWithArgument>(useConstructor = withArguments("Test")) {}
+
+ /* Then */
+ expect(result).toNotBeNull()
+ }
+
+ @Test
+ fun mockStubbing_withSettingsAPI_extraInterfaces() {
+ /* Given */
+ val mock = mock<Methods>(extraInterfaces = arrayOf(ExtraInterface::class)) {}
+
+ /* Then */
+ expect(mock).toBeInstanceOf<ExtraInterface>()
+ }
+
+ @Test
+ fun mockStubbing_withSettingsAPI_name() {
+ /* Given */
+ val mock = mock<Methods>(name = "myName") {}
+
+ /* When */
+ expectErrorWithMessage("myName.stringResult()") on {
+ verify(mock).stringResult()
+ }
+ }
+
+ @Test
+ fun mockStubbing_withSettingsAPIAndStubbing_name() {
+ /* Given */
+ val mock = mock<Methods>(name = "myName") {
+ on { nullableStringResult() } doReturn "foo"
+ }
+
+ /* When */
+ val result = mock.nullableStringResult()
+
+ /* Then */
+ expect(result).toBe("foo")
+ }
+
+ @Test
+ fun mockStubbing_withSettingsAPI_defaultAnswer() {
+ /* Given */
+ val mock = mock<Methods>(defaultAnswer = Mockito.RETURNS_MOCKS) {}
+
+ /* When */
+ val result = mock.nonDefaultReturnType()
+
+ /* Then */
+ expect(result).toNotBeNull()
+ }
+
+ @Test
+ fun mockStubbing_withSettingsAPI_serializable() {
+ /* Given */
+ val mock = mock<Methods>(serializable = true) {}
+
+ /* Then */
+ expect(mock).toBeInstanceOf<Serializable>()
+ }
+
+ @Test
+ fun mockStubbing_withSettingsAPI_serializableMode() {
+ /* Given */
+ val mock = mock<Methods>(serializableMode = BASIC) {}
+
+ /* Then */
+ expect(mock).toBeInstanceOf<Serializable>()
+ }
+
+ @Test
+ fun mockStubbing_withSettingsAPI_verboseLogging() {
+ /* Given */
+ val out = mock<PrintStream>()
+ System.setOut(out)
+ val mock = mock<Methods>(verboseLogging = true) {}
+
+ try {
+ /* When */
+ verify(mock).stringResult()
+ fail("Expected an exception")
+ } catch (e: WantedButNotInvoked) {
+ /* Then */
+ verify(out).println("methods.stringResult();")
+ }
+ }
+
+ @Test
+ fun mockStubbing_withSettingsAPI_invocationListeners() {
+ /* Given */
+ var bool = false
+ val mock = mock<Methods>(invocationListeners = arrayOf(InvocationListener { bool = true })) {}
+
+ /* When */
+ mock.stringResult()
+
+ /* Then */
+ expect(bool).toHold()
+ }
+
+ @Test
+ fun mockStubbing_withSettingsAPI_stubOnly() {
+ /* Given */
+ val mock = mock<Methods>(stubOnly = true) {}
+
+ /* Expect */
+ expectErrorWithMessage("is a stubOnly() mock") on {
+
+ /* When */
+ verify(mock).stringResult()
+ }
+ }
+
+ @Test
+ fun mockStubbing_withSettingsAPI_useConstructor() {
+ /* Given */
+ expectErrorWithMessage("Unable to create mock instance of type ") on {
+ mock<ThrowingConstructor>(useConstructor = parameterless()) {}
+ }
+ }
+
+ private interface MyInterface
+ private open class MyClass
+}
\ No newline at end of file
diff --git a/tests/src/test/kotlin/test/OngoingStubbingTest.kt b/tests/src/test/kotlin/test/OngoingStubbingTest.kt
new file mode 100644
index 0000000..3c9268e
--- /dev/null
+++ b/tests/src/test/kotlin/test/OngoingStubbingTest.kt
@@ -0,0 +1,340 @@
+package test
+
+import com.nhaarman.expect.expect
+import com.nhaarman.expect.expectErrorWithMessage
+import com.nhaarman.expect.fail
+import org.junit.Assume.assumeFalse
+import org.junit.Test
+import org.mockito.Mockito
+import org.mockito.exceptions.misusing.UnfinishedStubbingException
+import org.mockito.kotlin.*
+import org.mockito.stubbing.Answer
+import kotlin.check
+
+class OngoingStubbingTest : TestBase() {
+
+ @Test
+ fun testOngoingStubbing_methodCall() {
+ /* Given */
+ val mock = mock<Open>()
+ mock<Open> {
+ on(mock.stringResult()).doReturn("A")
+ }
+
+ /* When */
+ val result = mock.stringResult()
+
+ /* Then */
+ expect(result).toBe("A")
+ }
+
+ @Test
+ fun testOngoingStubbing_builder() {
+ /* Given */
+ val mock = mock<Methods> { mock ->
+ on { builderMethod() } doReturn mock
+ }
+
+ /* When */
+ val result = mock.builderMethod()
+
+ /* Then */
+ expect(result).toBeTheSameAs(mock)
+ }
+
+ @Test
+ fun testOngoingStubbing_nullable() {
+ /* Given */
+ val mock = mock<Methods> {
+ on { nullableStringResult() } doReturn "Test"
+ }
+
+ /* When */
+ val result = mock.nullableStringResult()
+
+ /* Then */
+ expect(result).toBe("Test")
+ }
+
+ @Test
+ fun testOngoingStubbing_doThrow() {
+ /* Given */
+ val mock = mock<Methods> {
+ on { builderMethod() } doThrow IllegalArgumentException()
+ }
+
+ try {
+ /* When */
+ mock.builderMethod()
+ fail("No exception thrown")
+ } catch (e: IllegalArgumentException) {
+ }
+ }
+
+ @Test
+ fun testOngoingStubbing_doThrowClass() {
+ /* Given */
+ val mock = mock<Methods> {
+ on { builderMethod() } doThrow IllegalArgumentException::class
+ }
+
+ try {
+ /* When */
+ mock.builderMethod()
+ fail("No exception thrown")
+ } catch (e: IllegalArgumentException) {
+ }
+ }
+
+ @Test
+ fun testOngoingStubbing_doThrowVarargs() {
+ /* Given */
+ val mock = mock<Methods> {
+ on { builderMethod() }.doThrow(
+ IllegalArgumentException(),
+ UnsupportedOperationException()
+ )
+ }
+
+ try {
+ /* When */
+ mock.builderMethod()
+ fail("No exception thrown")
+ } catch (e: IllegalArgumentException) {
+ }
+
+ try {
+ /* When */
+ mock.builderMethod()
+ fail("No exception thrown")
+ } catch (e: UnsupportedOperationException) {
+ }
+ }
+
+ @Test
+ fun testOngoingStubbing_doThrowClassVarargs() {
+ /* Given */
+ val mock = mock<Methods> {
+ on { builderMethod() }.doThrow(
+ IllegalArgumentException::class,
+ UnsupportedOperationException::class
+ )
+ }
+
+ try {
+ /* When */
+ mock.builderMethod()
+ fail("No exception thrown")
+ } catch (e: IllegalArgumentException) {
+ }
+
+ try {
+ /* When */
+ mock.builderMethod()
+ fail("No exception thrown")
+ } catch (e: UnsupportedOperationException) {
+ }
+ }
+
+ @Test
+ fun testOngoingStubbing_doAnswer_lambda() {
+ /* Given */
+ val mock = mock<Methods> {
+ on { stringResult() } doAnswer { "result" }
+ }
+
+ /* When */
+ val result = mock.stringResult()
+
+ /* Then */
+ expect(result).toBe("result")
+ }
+
+ @Test
+ fun testOngoingStubbing_doAnswer_instance() {
+ /* Given */
+ val mock = mock<Methods> {
+ on { stringResult() } doAnswer Answer<String> { "result" }
+ }
+
+ /* When */
+ val result = mock.stringResult()
+
+ /* Then */
+ expect(result).toBe("result")
+ }
+
+ @Test
+ fun testOngoingStubbing_doAnswer_returnsSelf() {
+ /* Given */
+ val mock = mock<Methods> {
+ on { builderMethod() } doAnswer Mockito.RETURNS_SELF
+ }
+
+ /* When */
+ val result = mock.builderMethod()
+
+ /* Then */
+ expect(result).toBe(mock)
+ }
+
+ @Test
+ fun testOngoingStubbing_doAnswer_withArgument() {
+ /* Given */
+ val mock = mock<Methods> {
+ on { stringResult(any()) } doAnswer { "${it.arguments[0]}-result" }
+ }
+
+ /* When */
+ val result = mock.stringResult("argument")
+
+ /* Then */
+ expect(result).toBe("argument-result")
+ }
+
+ @Test
+ fun testMockStubbingAfterCreatingMock() {
+ val mock = mock<Methods>()
+
+ //create stub after creation of mock
+ mock.stub {
+ on { stringResult() } doReturn "result"
+ }
+
+ /* When */
+ val result = mock.stringResult()
+
+ /* Then */
+ expect(result).toBe("result")
+ }
+
+ @Test
+ fun testOverrideDefaultStub() {
+ /* Given mock with stub */
+ val mock = mock<Methods> {
+ on { stringResult() } doReturn "result1"
+ }
+
+ /* override stub */
+ mock.stub {
+ on { stringResult() } doReturn "result2"
+ }
+
+ /* When */
+ val result = mock.stringResult()
+
+ /* Then */
+ expect(result).toBe("result2")
+ }
+
+
+ @Test
+ fun stubbingTwiceWithArgumentMatchers() {
+ /* When */
+ val mock = mock<Methods> {
+ on { stringResult(argThat { this == "A" }) } doReturn "A"
+ on { stringResult(argThat { this == "B" }) } doReturn "B"
+ }
+
+ /* Then */
+ expect(mock.stringResult("A")).toBe("A")
+ expect(mock.stringResult("B")).toBe("B")
+ }
+
+ @Test
+ fun stubbingTwiceWithCheckArgumentMatchers_throwsException() {
+ /* Expect */
+ expectErrorWithMessage("null").on {
+ mock<Methods> {
+ on { stringResult(check { }) } doReturn "A"
+ on { stringResult(check { }) } doReturn "B"
+ }
+ }
+ }
+
+ @Test
+ fun doReturn_withSingleItemList() {
+ /* Given */
+ val mock = mock<Open> {
+ on { stringResult() } doReturnConsecutively listOf("a", "b")
+ }
+
+ /* Then */
+ expect(mock.stringResult()).toBe("a")
+ expect(mock.stringResult()).toBe("b")
+ }
+
+ @Test
+ fun doReturn_throwsNPE() {
+ assumeFalse(mockMakerInlineEnabled())
+ expectErrorWithMessage("look at the stack trace below") on {
+
+ /* When */
+ mock<Open> {
+ on { throwsNPE() } doReturn "result"
+ }
+ }
+ }
+
+ @Test
+ fun doReturn_withGenericIntReturnType_on() {
+ /* Expect */
+ expectErrorWithMessage("onGeneric") on {
+
+ /* When */
+ mock<GenericMethods<Int>> {
+ on { genericMethod() } doReturn 2
+ }
+ }
+ }
+
+ @Test
+ fun doReturn_withGenericIntReturnType_onGeneric() {
+ /* Given */
+ val mock = mock<GenericMethods<Int>> {
+ onGeneric { genericMethod() } doReturn 2
+ }
+
+ /* Then */
+ expect(mock.genericMethod()).toBe(2)
+ }
+
+ @Test
+ fun doReturn_withGenericNullableReturnType_onGeneric() {
+ val m = mock<GenericMethods<String>> {
+ onGeneric { nullableReturnType() } doReturn "Test"
+ }
+
+ expect(m.nullableReturnType()).toBe("Test")
+ }
+
+ @Test
+ fun stubbingExistingMock() {
+ /* Given */
+ val mock = mock<Methods>()
+
+ /* When */
+ stubbing(mock) {
+ on { stringResult() } doReturn "result"
+ }
+
+ /* Then */
+ expect(mock.stringResult()).toBe("result")
+ }
+
+ @Test
+ fun testMockitoStackOnUnfinishedStubbing() {
+ /* Given */
+ val mock = mock<Open>()
+ whenever(mock.stringResult())
+
+ /* When */
+ try {
+ mock.stringResult()
+ } catch (e: UnfinishedStubbingException) {
+ /* Then */
+ expect(e.message).toContain("Unfinished stubbing detected here:")
+ expect(e.message).toContain("-> at test.OngoingStubbingTest.testMockitoStackOnUnfinishedStubbing")
+ }
+ }
+}
diff --git a/tests/src/test/kotlin/test/SpyTest.kt b/tests/src/test/kotlin/test/SpyTest.kt
new file mode 100644
index 0000000..500faee
--- /dev/null
+++ b/tests/src/test/kotlin/test/SpyTest.kt
@@ -0,0 +1,141 @@
+package test
+
+/*
+ * The MIT License
+ *
+ * Copyright (c) 2016 Niek Haarman
+ * Copyright (c) 2007 Mockito contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+import com.nhaarman.expect.expect
+import org.junit.After
+import org.junit.Test
+import org.mockito.Mockito
+import org.mockito.kotlin.*
+import java.util.*
+
+class SpyTest : TestBase() {
+
+ private val interfaceInstance: MyInterface = MyClass()
+ private val openClassInstance: MyClass = MyClass()
+ private val closedClassInstance: ClosedClass = ClosedClass()
+
+ @After
+ override fun tearDown() {
+ super.tearDown()
+ Mockito.validateMockitoUsage()
+ }
+
+ @Test
+ fun spyInterfaceInstance() {
+ /* When */
+ val result = spy(interfaceInstance)
+
+ /* Then */
+ expect(result).toNotBeNull()
+ }
+
+ @Test
+ fun spyOpenClassInstance() {
+ /* When */
+ val result = spy(openClassInstance)
+
+ /* Then */
+ expect(result).toNotBeNull()
+ }
+
+ @Test
+ fun doReturnWithSpy() {
+ val date = spy(Date())
+ doReturn(123L).whenever(date).time
+ expect(date.time).toBe(123L)
+ }
+
+ @Test
+ fun doNothingWithSpy() {
+ val date = spy(Date(0))
+ doNothing().whenever(date).time = 5L
+ date.time = 5L
+ expect(date.time).toBe(0L)
+ }
+
+ @Test(expected = IllegalArgumentException::class)
+ fun doThrowWithSpy() {
+ val date = spy(Date(0))
+ doThrow(IllegalArgumentException()).whenever(date).time
+ date.time
+ }
+
+ @Test
+ fun doCallRealMethodWithSpy() {
+ val date = spy(Date(0))
+ doReturn(123L).whenever(date).time
+ doCallRealMethod().whenever(date).time
+ expect(date.time).toBe(0L)
+ }
+
+ @Test
+ fun doReturnWithDefaultInstanceSpyStubbing() {
+ val timeVal = 12L
+
+ val dateSpy = spy<Date> {
+ on { time } doReturn timeVal
+ }
+
+ expect(dateSpy.time).toBe(timeVal)
+ }
+
+ @Test
+ fun doReturnWithSpyStubbing() {
+ val timeVal = 15L
+
+ val dateSpy = spy(Date(0)) {
+ on { time } doReturn timeVal
+ }
+
+ expect(dateSpy.time).toBe(timeVal)
+ }
+
+ @Test
+ fun passAnyStringToSpy() {
+ /* Given */
+ val my = spy(MyClass())
+
+ /* When */
+ doReturn("mocked").whenever(my).foo(any())
+
+ /* Then */
+ expect(my.foo("hello")).toBe("mocked")
+ }
+
+ private interface MyInterface {
+
+ fun foo(value: String): String
+ }
+
+ private open class MyClass : MyInterface {
+
+ override fun foo(value: String): String = value
+ }
+
+ private class ClosedClass
+}
+
diff --git a/tests/src/test/kotlin/test/StubberTest.kt b/tests/src/test/kotlin/test/StubberTest.kt
new file mode 100644
index 0000000..eb6e28c
--- /dev/null
+++ b/tests/src/test/kotlin/test/StubberTest.kt
@@ -0,0 +1,103 @@
+package test
+
+import com.nhaarman.expect.expect
+import com.nhaarman.expect.expectErrorWithMessage
+import org.junit.Test
+import org.mockito.kotlin.*
+
+class StubberTest : TestBase() {
+
+ @Test
+ fun testDoAnswer() {
+ val mock = mock<Methods>()
+
+ doAnswer { "Test" }
+ .whenever(mock)
+ .stringResult()
+
+ expect(mock.stringResult()).toBe("Test")
+ }
+
+ @Test
+ fun testDoCallRealMethod() {
+ val mock = mock<Open>()
+
+ doReturn("Test").whenever(mock).stringResult()
+ doCallRealMethod().whenever(mock).stringResult()
+
+ expect(mock.stringResult()).toBe("Default")
+ }
+
+ @Test
+ fun testDoNothing() {
+ val spy = spy(Open())
+ val array = intArrayOf(3)
+
+ doNothing().whenever(spy).modifiesContents(array)
+ spy.modifiesContents(array)
+
+ expect(array[0]).toBe(3)
+ }
+
+ @Test
+ fun testDoReturnValue() {
+ val mock = mock<Methods>()
+
+ doReturn("test").whenever(mock).stringResult()
+
+ expect(mock.stringResult()).toBe("test")
+ }
+
+ @Test
+ fun testDoReturnNullValue() {
+ val mock = mock<Methods>()
+
+ doReturn(null).whenever(mock).stringResult()
+
+ expect(mock.stringResult()).toBeNull()
+ }
+
+ @Test
+ fun testDoReturnNullValues() {
+ val mock = mock<Methods>()
+
+ doReturn(null, null).whenever(mock).stringResult()
+
+ expect(mock.stringResult()).toBeNull()
+ expect(mock.stringResult()).toBeNull()
+ }
+
+ @Test
+ fun testDoReturnValues() {
+ val mock = mock<Methods>()
+
+ doReturn("test", "test2").whenever(mock).stringResult()
+
+ expect(mock.stringResult()).toBe("test")
+ expect(mock.stringResult()).toBe("test2")
+ }
+
+ @Test
+ fun testDoThrowClass() {
+ val mock = mock<Open>()
+
+ doThrow(IllegalStateException::class).whenever(mock).go()
+
+ try {
+ mock.go()
+ throw AssertionError("Call should have thrown.")
+ } catch (e: IllegalStateException) {
+ }
+ }
+
+ @Test
+ fun testDoThrow() {
+ val mock = mock<Open>()
+
+ doThrow(IllegalStateException("test")).whenever(mock).go()
+
+ expectErrorWithMessage("test").on {
+ mock.go()
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/src/test/kotlin/test/TestBase.kt b/tests/src/test/kotlin/test/TestBase.kt
new file mode 100644
index 0000000..95c76ec
--- /dev/null
+++ b/tests/src/test/kotlin/test/TestBase.kt
@@ -0,0 +1,11 @@
+package test
+
+import org.junit.After
+
+abstract class TestBase {
+
+ @After
+ open fun tearDown() {
+ mockMakerInlineEnabled = null
+ }
+}
\ No newline at end of file
diff --git a/tests/src/test/kotlin/test/VerificationTest.kt b/tests/src/test/kotlin/test/VerificationTest.kt
new file mode 100644
index 0000000..f2f92fd
--- /dev/null
+++ b/tests/src/test/kotlin/test/VerificationTest.kt
@@ -0,0 +1,115 @@
+package test
+
+import com.nhaarman.expect.expect
+import org.junit.Test
+import org.mockito.exceptions.base.MockitoAssertionError
+import org.mockito.kotlin.*
+import org.mockito.kotlin.verify
+
+class VerificationTest : TestBase() {
+
+ @Test
+ fun atLeastXInvocations() {
+ mock<Methods>().apply {
+ string("")
+ string("")
+
+ verify(this, atLeast(2)).string(any())
+ }
+ }
+
+ @Test
+ fun testAtLeastOnce() {
+ mock<Methods>().apply {
+ string("")
+ string("")
+
+ verify(this, atLeastOnce()).string(any())
+ }
+ }
+
+ @Test
+ fun atMostXInvocations() {
+ mock<Methods>().apply {
+ string("")
+ string("")
+
+ verify(this, atMost(2)).string(any())
+ }
+ }
+
+ @Test
+ fun testCalls() {
+ mock<Methods>().apply {
+ string("")
+ string("")
+
+ inOrder(this).verify(this, calls(2)).string(any())
+ }
+ }
+
+ @Test
+ fun testInOrderWithLambda() {
+ /* Given */
+ val a = mock<() -> Unit>()
+ val b = mock<() -> Unit>()
+
+ /* When */
+ b()
+ a()
+
+ /* Then */
+ inOrder(a, b) {
+ verify(b).invoke()
+ verify(a).invoke()
+ }
+ }
+
+ @Test
+ fun testInOrderWithReceiver() {
+ /* Given */
+ val mock = mock<Methods>()
+
+ /* When */
+ mock.string("")
+ mock.int(0)
+
+ /* Then */
+ mock.inOrder {
+ verify().string(any())
+ verify().int(any())
+ verifyNoMoreInteractions()
+ }
+ }
+
+ @Test
+ fun testClearInvocations() {
+ val mock = mock<Methods>().apply {
+ string("")
+ }
+
+ clearInvocations(mock)
+
+ verify(mock, never()).string(any())
+ }
+
+ @Test
+ fun testDescription() {
+ try {
+ mock<Methods>().apply {
+ verify(this, description("Test")).string(any())
+ }
+ throw AssertionError("Verify should throw Exception.")
+ } catch (e: MockitoAssertionError) {
+ expect(e.message).toContain("Test")
+ }
+ }
+
+ @Test
+ fun testAfter() {
+ mock<Methods>().apply {
+ int(3)
+ verify(this, after(10)).int(3)
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/src/test/kotlin/test/VerifyTest.kt b/tests/src/test/kotlin/test/VerifyTest.kt
new file mode 100644
index 0000000..0a93832
--- /dev/null
+++ b/tests/src/test/kotlin/test/VerifyTest.kt
@@ -0,0 +1,96 @@
+package test
+
+import org.mockito.kotlin.any
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.verify
+import org.junit.Test
+import org.mockito.exceptions.verification.TooLittleActualInvocations
+import org.mockito.exceptions.verification.junit.ArgumentsAreDifferent
+
+class VerifyTest : TestBase() {
+
+ @Test
+ fun verify0Calls() {
+ val iface = mock<TestInterface>()
+
+ verify(iface) {
+ 0 * { call(any()) }
+ }
+ }
+
+ @Test
+ fun verifyNCalls() {
+ val iface = mock<TestInterface>()
+
+ iface.call(42)
+ iface.call(42)
+
+ verify(iface) {
+ 2 * { call(42) }
+ }
+ }
+
+ @Test(expected = TooLittleActualInvocations::class)
+ fun verifyFailsWithWrongCount() {
+ val iface = mock<TestInterface>()
+
+ iface.call(0)
+
+ verify(iface) {
+ 2 * { call(0) }
+ }
+ }
+
+ @Test(expected = ArgumentsAreDifferent::class)
+ fun verifyFailsWithWrongArg() {
+ val iface = mock<TestInterface>()
+
+ iface.call(3)
+
+ verify(iface) {
+ 1 * { call(0) }
+ }
+ }
+
+ @Test
+ fun verifyDefaultArgs_firstParameter() {
+ /* Given */
+ val m = mock<TestInterface>()
+
+ /* When */
+ m.defaultArgs(a = 2)
+
+ /* Then */
+ verify(m).defaultArgs(2)
+ }
+
+ @Test
+ fun verifyDefaultArgs_secondParameter() {
+ /* Given */
+ val m = mock<TestInterface>()
+
+ /* When */
+ m.defaultArgs(b = 2)
+
+ /* Then */
+ verify(m).defaultArgs(b = 2)
+ }
+
+ @Test
+ fun verifyDefaultArgs_verifyDefaultValue() {
+ /* Given */
+ val m = mock<TestInterface>()
+
+ /* When */
+ m.defaultArgs(b = 2)
+
+ /* Then */
+ verify(m).defaultArgs(a = 3, b = 2)
+ }
+
+ interface TestInterface {
+ fun call(arg: Int)
+
+ fun defaultArgs(a: Int = 3, b: Int = 42)
+ }
+}
\ No newline at end of file
diff --git a/tests/src/test/kotlin/test/createinstance/NullCasterTest.kt b/tests/src/test/kotlin/test/createinstance/NullCasterTest.kt
new file mode 100644
index 0000000..6d160c7
--- /dev/null
+++ b/tests/src/test/kotlin/test/createinstance/NullCasterTest.kt
@@ -0,0 +1,31 @@
+package test.createinstance
+
+import com.nhaarman.expect.expect
+import org.mockito.kotlin.internal.createInstance
+import org.junit.Test
+import test.TestBase
+
+
+class NullCasterTest : TestBase() {
+
+ @Test
+ fun createInstance() {
+ /* When */
+ val result = createInstance(String::class)
+
+ /* Then */
+ expect(result).toBeNull()
+ }
+
+ @Test
+ fun kotlinAcceptsNullValue() {
+ /* Given */
+ val s: String = createInstance(String::class)
+
+ /* When */
+ acceptNonNullableString(s)
+ }
+
+ private fun acceptNonNullableString(@Suppress("UNUSED_PARAMETER") s: String) {
+ }
+}
diff --git a/tests/src/test/kotlin/test/inline/UsingMockMakerInlineTest.kt b/tests/src/test/kotlin/test/inline/UsingMockMakerInlineTest.kt
new file mode 100644
index 0000000..b03d77e
--- /dev/null
+++ b/tests/src/test/kotlin/test/inline/UsingMockMakerInlineTest.kt
@@ -0,0 +1,116 @@
+/*
+ * The MIT License
+ *
+ * Copyright (c) 2016 Ian J. De Silva
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+import com.nhaarman.expect.expect
+import org.junit.Assume.assumeTrue
+import org.junit.Before
+import org.junit.Test
+import org.mockito.kotlin.*
+import test.mockMakerInlineEnabled
+import java.io.IOException
+import java.math.BigInteger
+
+class UsingMockMakerInlineTest {
+
+ class ClassToBeMocked {
+
+ fun doSomething(@Suppress("UNUSED_PARAMETER") c: ClassToBeMocked) {
+ }
+
+ fun doSomethingElse(value: BigInteger): BigInteger {
+ return value.plus(BigInteger.ONE)
+ }
+ }
+
+ @Before
+ fun setup() {
+ mockMakerInlineEnabled = null
+ assumeTrue(mockMakerInlineEnabled())
+ }
+
+ @Test
+ fun mockClosedClass() {
+ /* When */
+ val result = mock<ClassToBeMocked>()
+
+ /* Then */
+ expect(result).toNotBeNull()
+ }
+
+ @Test
+ fun anyClosedClass() {
+ /* Given */
+ val mock = mock<ClassToBeMocked>()
+
+ /* When */
+ mock.doSomething(mock)
+
+ /* Then */
+ verify(mock).doSomething(any())
+ }
+
+ @Test
+ fun mockClosedFunction_mockStubbing() {
+ /* Given */
+ val mock = mock<ClassToBeMocked> {
+ on { doSomethingElse(any()) } doReturn (BigInteger.ONE)
+ }
+
+ /* When */
+ val result = mock.doSomethingElse(BigInteger.TEN)
+
+ /* Then */
+ expect(result).toBe(BigInteger.ONE)
+ }
+
+ @Test
+ fun mockClosedFunction_whenever() {
+ /* Given */
+ val mock = mock<ClassToBeMocked>()
+ whenever(mock.doSomethingElse(any())).doReturn(BigInteger.ONE)
+
+ /* When */
+ val result = mock.doSomethingElse(BigInteger.TEN)
+
+ /* Then */
+ expect(result).toBe(BigInteger.ONE)
+ }
+
+ /** https://github.com/nhaarman/mockito-kotlin/issues/27 */
+ @Test
+ fun anyThrowableWithSingleThrowableConstructor() {
+ mock<Methods>().apply {
+ throwableClass(ThrowableClass(IOException()))
+ verify(this).throwableClass(any())
+ }
+ }
+
+ interface Methods {
+
+ fun throwableClass(t: ThrowableClass)
+ }
+
+ class ThrowableClass(cause: Throwable) : Throwable(cause)
+
+}
diff --git a/update_source.sh b/update_source.sh
new file mode 100644
index 0000000..52848d2
--- /dev/null
+++ b/update_source.sh
@@ -0,0 +1,53 @@
+#!/bin/bash
+#
+# Copyright 2023 The Android Open Source Project.
+#
+# Retrieves the current mockito-kotlin source code into the current directory
+
+# Force stop on first error.
+set -e
+
+if [ $# -ne 1 ]; then
+ echo "$0 <version>" >&2
+ exit 1;
+fi
+
+if [ -z "$ANDROID_BUILD_TOP" ]; then
+ echo "Missing environment variables. Did you run build/envsetup.sh and lunch?" >&2
+ exit 1
+fi
+
+VERSION=${1}
+
+SOURCE="git://github.com/mockito/mockito-kotlin.git"
+INCLUDE="
+ LICENSE
+ mockito-kotlin/src/main
+ "
+
+working_dir="$(mktemp -d)"
+trap "echo \"Removing temporary directory\"; rm -rf $working_dir" EXIT
+
+echo "Fetching mockito-kotlin source into $working_dir"
+git clone $SOURCE $working_dir/source
+(cd $working_dir/source; git checkout $VERSION)
+
+for include in ${INCLUDE}; do
+ echo "Updating $include"
+ rm -rf $include
+ mkdir -p $(dirname $include)
+ cp -R $working_dir/source/$include $include
+done;
+
+echo "Done"
+
+# Update the version.
+perl -pi -e "s|^Version: .*$|Version: ${VERSION}|" "README.version"
+
+# Remove any documentation about local modifications.
+mv README.version README.tmp
+grep -B 100 "Local Modifications" README.tmp > README.version
+echo " None" >> README.version
+rm README.tmp
+
+echo "Done"
diff --git a/version.properties b/version.properties
new file mode 100644
index 0000000..708e7ad
--- /dev/null
+++ b/version.properties
@@ -0,0 +1,4 @@
+# Version of the produced binaries.
+# The version is inferred by shipkit-auto-version Gradle plugin (https://github.com/shipkit/shipkit-auto-version)
+version=2.2.*
+tagPrefix=
\ No newline at end of file