https://github.com/anthonycr/mockingbird
A minimalist faking framework exclusively for verifying interactions
https://github.com/anthonycr/mockingbird
kotlin mock testing verification
Last synced: 6 months ago
JSON representation
A minimalist faking framework exclusively for verifying interactions
- Host: GitHub
- URL: https://github.com/anthonycr/mockingbird
- Owner: anthonycr
- License: mit
- Created: 2024-03-15T01:15:35.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2024-10-24T04:11:59.000Z (over 1 year ago)
- Last Synced: 2024-10-24T18:19:11.558Z (over 1 year ago)
- Topics: kotlin, mock, testing, verification
- Language: Kotlin
- Homepage:
- Size: 291 KB
- Stars: 3
- Watchers: 1
- Forks: 2
- Open Issues: 4
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# Mockingbird
A minimalist faking framework exclusively for verifying interactions. It generates fake
implementations of interfaces and abstract classes that can be verified during a test using the
Kotlin compiler plugin API. It does not allow mocking behavior or return values, and does not
support mocking concrete classes.
## Why?
Other testing frameworks exist, like MockK, that support full mocking of all types, a wide range of
features, and have significantly more utility than this minimalist framework. However, mocking
objects is frequently viewed as an anti-pattern, as mocking an object can cover up poor class design
by making untestable code testable. Tests that heavily utilize mocks can lose their utility and even
obscure bugs, or can become difficult to understand and refactor. Additionally, mocks are usually
slow to construct, which in turn slows down test execution.
Fakes are less forgiving then mocks and require better class design in order to support testing.
Because they are less flexible, they have less potential to be abused. However, it can be annoying
to verify interactions on fakes because they are usually handwritten. Mockingbird auto-generates
fake implementations of interfaces and abstract classes that have `Unit` function types - types
usually performing side effects that are most often verified by a mocking framework.
## Usage

Mockingbird is available on Maven Central and through the Gradle Plugin Portal. Include the
following dependencies in your `build.gradle.kts` file.
```kotlin
plugins {
kotlin("jvm") version ""
id("com.anthonycr.plugins.mockingbird") version ""
}
```
Then add the build dependencies to the `dependencies` block.
```kotlin
dependencies {
testImplementation("com.anthonycr.mockingbird:core:")
}
```
Within your test, add the following annotation to a property that you wish to verify. Note that the
property you are verifying must be an interface or abstract class with a zero argument constructor.
All functions you wish to verify must return `Unit` and when verifying an abstract class, the
function must be abstract.
```kotlin
import com.anthonycr.mockingbird.core.Verify
import com.anthonycr.mockingbird.core.fake
import com.anthonycr.mockingbird.core.verify
interface Analytics {
fun trackEvent(event: String)
fun trackError(exception: Exception)
}
class ClassToTest(private val analytics: Analytics) {
fun doSomething() {
analytics.trackEvent("doSomething was called!")
}
fun doSomethingElse() {
analytics.trackError(RuntimeException("Something went wrong"))
}
}
class ClassToTestTest {
val analytics: Analytics = fake()
@Test
fun `analytics event for doSomething was triggered`() {
val classToTest = ClassToTest(analytics)
classToTest.doSomething()
verify(analytics) {
analytics.trackEvent("doSomething was called!")
}
}
@Test
fun `analytics error for doSomethingElse was triggered`() {
val classToTest = ClassToTest(analytics)
classToTest.doSomethingElse()
verify(analytics) {
analytics.trackError(sameAs { e -> e.message == "Something went wrong") })
}
}
}
```
There are 3 `verify*` functions.
1. `verify`: This function accepts all the parameters that you wish to verify, performs the
verifications, and finally asserts that there are no unverified invocations.
2. `verifyPartial`: This function behaves similarly to `verify`, except that it does not assert that
there are no unverified invocations at the end.
3. `verifyComplete`: This function verifies that there are no unverified invocations left. This is
useful if you want to verify that no functions were called, or if you are using `verifyPartial`
and want to assert that one of the subjects being verified is actually fully verified.
There are 2 matcher functions that can be used to match parameters outside of basic equality.
1. `sameAs`: Asserts that the value passed in matches using the lambda matcher.
2. `any`: Accepts any parameter, useful for dynamic values or values that you really don't care
about asserting in your test.
## Benchmark
Run `./benchmark.sh` to execute a benchmark comparison of Mockingbird to Mockk. There are two Mockk
benchmarks. The first, `mockk-interface` just mocks an interface. The second, `mockk-static` uses a
static mock to simulate the worst case scenario for mockk, since static mocks are the most expensive
mocks to run. The benchmark code generates the tests according to the input parameters and then runs
the tests, recording the time it takes to generate the tests, compile the tests, and run the tests.
See the README files for each benchmark ([mockingbird](benchmark/mockingbird/README.md),
[mockk-interface](benchmark/mockk-interface/README.md),
[mockk-static](benchmark/mockk-static/README.md)) for more information about the performance
characteristics of each approach.
### Current benchmark runtimes (3 July 2025)
#### Parameters
- 3 classes to be verified
- 500 tests
- Apple M4 Pro
#### Results
- Mockingbird: 10.1 seconds
- Mockk (Interface): 40.8 seconds
- Mockk (Static): 82.0 seconds