Skip to content

Commit

Permalink
Move TestWithMocks logic into ITestsWithMocks so that it can be u…
Browse files Browse the repository at this point in the history
…sed in test classes that extend something else (fixes #50).
  • Loading branch information
SalomonBrys committed May 7, 2023
1 parent 2af48b3 commit f8da6ef
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 42 deletions.
19 changes: 19 additions & 0 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,7 @@ As soon as a class `T` contains a `@Mock` or `@Fake` annotated property, a `T.in

IMPORTANT: Don't forget to `reset` the `Mocker` in a `@BeforeTest` method!


[[test-helper]]
=== Using the test class helper

Expand Down Expand Up @@ -633,6 +634,24 @@ class MyTests : TestsWithMocks() {
----
====

In case your test class already extends another class, you can use the `ITestsWithMocks` interface instead:

[source,kotlin]
----
@UsesFakes(User::class)
class MyTests : MySuperAbstractTests(), ITestsWithMocks { //<1>
override val mocksState = ITestsWithMocks.State() //<2>
override fun setUpMocks() = injectMocks(mocker)
// ...your tests...
}
----
<1> The class implements the `ITestsWithMocks` interface, which provides all helper methods.
<2> The class needs to provide an `ITestsWithMocks.State` (since the interface cannot provide one).


== Setup

=== With the official plugin
Expand Down
2 changes: 1 addition & 1 deletion settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ buildscript {
maven(url = "https://raw.githubusercontent.com/kosi-libs/kodein-internal-gradle-plugin/mvn-repo")
}
dependencies {
classpath("org.kodein.internal.gradle:kodein-internal-gradle-settings:8.0.2")
classpath("org.kodein.internal.gradle:kodein-internal-gradle-settings:8.1.1")
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package org.kodein.mock.tests

import org.kodein.mock.ArgConstraintsBuilder
import org.kodein.mock.Mocker
import org.kodein.mock.VerificationBuilder
import kotlin.test.BeforeTest


public interface ITestsWithMocks {

public class State {
private val defs = ArrayList<TestsWithMocks.Deferred<*>>()
public val mocker: Mocker = Mocker()

public fun initDeferred() {
defs.forEach { it.init() }
}

public fun clearDeferred() {
defs.forEach { it.clear() }
}

public fun <T : Any> withMocks(create: () -> T): TestsWithMocks.Deferred<T> = TestsWithMocks.Deferred(create).also { defs.add(it) }
}

public val mocksState: State

public val mocker: Mocker get() = mocksState.mocker

public fun initDeferred(): Unit = mocksState.initDeferred()

public fun clearDeferred(): Unit = mocksState.clearDeferred()

public fun <T : Any> withMocks(create: () -> T): TestsWithMocks.Deferred<T> = mocksState.withMocks(create)

public fun <T> every(block: ArgConstraintsBuilder.() -> T) : Mocker.Every<T> =
mocker.every(block)
public suspend fun <T> everySuspending(block: suspend ArgConstraintsBuilder.() -> T) : Mocker.EverySuspend<T> =
mocker.everySuspending(block)

public fun verify(exhaustive: Boolean = true, inOrder: Boolean = true, block: VerificationBuilder.() -> Unit): Unit =
mocker.verify(exhaustive = exhaustive, inOrder = inOrder, block)
public suspend fun verifyWithSuspend(exhaustive: Boolean = true, inOrder: Boolean = true, block: suspend VerificationBuilder.() -> Unit): Unit =
mocker.verifyWithSuspend(exhaustive = exhaustive, inOrder = inOrder, block)

@BeforeTest
public fun injectMocksBeforeTest() {
mocker.reset()
setUpMocks()
initDeferred()
initMocksBeforeTest()
}

public fun setUpMocks()

public fun initMocksBeforeTest() {}

}
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
package org.kodein.mock.tests

import org.kodein.mock.ArgConstraintsBuilder
import org.kodein.mock.Mocker
import org.kodein.mock.VerificationBuilder
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
import kotlin.test.BeforeTest


public abstract class TestsWithMocks {
public abstract class TestsWithMocks : ITestsWithMocks {

public class Deferred<T : Any>(private val create: () -> T) : ReadWriteProperty<Any, T> {
public class Deferred<T : Any> internal constructor(private val create: () -> T) : ReadWriteProperty<Any, T> {
private var value: T? = null
internal fun init() {
if (value == null) value = create()
Expand All @@ -27,39 +23,5 @@ public abstract class TestsWithMocks {
}
}

private val defs = ArrayList<Deferred<*>>()

public val mocker: Mocker = Mocker()

protected fun initDeferred() {
defs.forEach { it.init() }
}

protected fun clearDeferred() {
defs.forEach { it.clear() }
}

protected fun <T : Any> withMocks(create: () -> T): Deferred<T> = Deferred(create)

@BeforeTest
public fun injectMocksBeforeTest() {
mocker.reset()
setUpMocks()
initDeferred()
initMocksBeforeTest()
}

public open fun initMocksBeforeTest() {}

protected abstract fun setUpMocks()

public fun <T> every(block: ArgConstraintsBuilder.() -> T) : Mocker.Every<T> =
mocker.every(block)
public suspend fun <T> everySuspending(block: suspend ArgConstraintsBuilder.() -> T) : Mocker.EverySuspend<T> =
mocker.everySuspending(block)

public fun verify(exhaustive: Boolean = true, inOrder: Boolean = true, block: VerificationBuilder.() -> Unit): Unit =
mocker.verify(exhaustive = exhaustive, inOrder = inOrder, block)
public suspend fun verifyWithSuspend(exhaustive: Boolean = true, inOrder: Boolean = true, block: suspend VerificationBuilder.() -> Unit): Unit =
mocker.verifyWithSuspend(exhaustive = exhaustive, inOrder = inOrder, block)
final override val mocksState: ITestsWithMocks.State = ITestsWithMocks.State()
}

0 comments on commit f8da6ef

Please sign in to comment.