Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,12 @@
package org.mockito.kotlin

import org.mockito.MockedStatic
import org.mockito.stubbing.OngoingStubbing
import org.mockito.verification.VerificationMode

fun <S, T> MockedStatic<T>.whenever(verification: () -> S): OngoingStubbing<S> =
`when` { verification() }

/**
* Syntax sugar to enable [SAM conversion syntax](https://kotlinlang.org/docs/java-interop.html#sam-conversions)
* for [MockedStatic.verify] with a [VerificationMode].
Expand Down
30 changes: 30 additions & 0 deletions mockito-kotlin/src/main/kotlin/org/mockito/kotlin/Mocking.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ package org.mockito.kotlin

import org.mockito.Incubating
import org.mockito.MockSettings
import org.mockito.MockedConstruction
import org.mockito.MockedStatic
import org.mockito.Mockito
import org.mockito.listeners.InvocationListener
import org.mockito.mock.SerializableMode
Expand Down Expand Up @@ -179,6 +181,34 @@ fun withSettings(
if (lenient) strictness(Strictness.LENIENT)
}

/**
* Creates a thread-local mock for static methods on [T].
*
* @see Mockito.mockStatic
*/
inline fun <reified T> mockStatic(): MockedStatic<T> {
return Mockito.mockStatic(T::class.java)
}

/**
* Creates a thread-local mock for constructions of [T].
*
* @see Mockito.mockConstruction
*/
inline fun <reified T> mockConstruction(): MockedConstruction<T> {
return Mockito.mockConstruction(T::class.java)
}

/**
* Creates a thread-local mock for constructions of [T].
*
* @param mockInitializer a callback to prepare the methods on a mock after its instantiation
* @see Mockito.mockConstruction
*/
inline fun <reified T> mockConstruction(mockInitializer: MockedConstruction.MockInitializer<T>): MockedConstruction<T> {
return Mockito.mockConstruction(T::class.java, mockInitializer)
}

class UseConstructor private constructor(val args: Array<Any>) {

companion object {
Expand Down
3 changes: 3 additions & 0 deletions tests/src/test/kotlin/test/Classes.kt
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,7 @@ class ThrowableClass(cause: Throwable) : Throwable(cause)
object SomeObject {
@JvmStatic
fun aStaticMethod() {}

@JvmStatic
fun aStaticMethodReturningString(): String = "Some Value"
}
35 changes: 35 additions & 0 deletions tests/src/test/kotlin/test/MockingTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import org.mockito.Mockito
import org.mockito.exceptions.verification.WantedButNotInvoked
import org.mockito.invocation.DescribedInvocation
import org.mockito.kotlin.argumentCaptor
import org.mockito.kotlin.mockConstruction
import org.mockito.kotlin.mockStatic
import org.mockito.listeners.InvocationListener
import org.mockito.mock.SerializableMode.BASIC
import java.io.PrintStream
Expand Down Expand Up @@ -388,6 +390,39 @@ class MockingTest : TestBase() {
}
}

@Test
fun mockStatic_stubbing() {
mockStatic<SomeObject>().use { mockedStatic ->
mockedStatic.whenever { SomeObject.aStaticMethodReturningString() }.thenReturn("Hello")

expect(SomeObject.aStaticMethodReturningString()).toBe("Hello")

mockedStatic.verify { SomeObject.aStaticMethodReturningString() }
}
}

@Test
fun mockConstruction_basic() {
mockConstruction<Open>().use { mockedConstruction ->
val open = Open()

expect(mockedConstruction.constructed()).toHaveSize(1)
expect(mockedConstruction.constructed().first()).toBeTheSameAs(open)
}
}

@Test
fun mockConstruction_withInitializer() {
mockConstruction<Open> { mock, _ ->
whenever(mock.stringResult()).thenReturn("Hello")
}.use {
val open = Open()

expect(open.stringResult()).toBe("Hello")
}
}


private interface MyInterface
private open class MyClass
}