Project Setup
Ideally, mockspresso should only be exposed to tests via a dedicated gradle module. This lets us define MockspressoBuilder with defaults appropriate to our project and prevents accidental usage of the default MockspressoBuilder()
entry-point.
Gradle setup
def mxoVersion = '2.0.1'
dependencies {
// expose the api to other modules
api "com.episode6.mockspresso2:api:$mxoVersion"
// hide the core module from other modules
implementation "com.episode6.mockspresso2:core:$mxoVersion"
}
Entry-point in dedicated gradle module
package com.sample.myproject.testsupport
// define a simple custom entry-point for your project
fun MockspressoBuilder(): MockspressoBuilder = com.episode6.mockspresso2.MockspressoBuilder()
.makeRealObjectsUsingPrimaryConstructor()
Entry-point in single module project
It may not be feasible to dedicate a module to mockspresso support. In that case it’s better to avoid duplicating the MockspressoBuilder()
entry-point and prefer defining a withDefaults()
plugin for all tests to apply…
// test-support code
fun MockspressoBuilder.withDefaults(): MockspressoBuilder = this
.makeRealObjectsUsingPrimaryConstructor()
// Usage example:
class MyTest {
// use built-in entry-point but require defaults plugin as a best-practice
val mxo = MockspressoBuilder().withDefaults()
.build()
}
Auto-Mock support
Mockspresso is agnostic to mocks and should work with any mocking framework that works with kotlin, but we do offer plugin modules to add fallback support (a.k.a. auto-mocking) with Mockk (using plugins-mockk
) or Mockito (using plugins-mockito
)
dependencies {
api "com.episode6.mockspresso2:plugins-mockito:$mxoVersion"
// OR
api "com.episode6.mockspresso2:plugins-mockk:$mxoVersion"
}
Add auto-mock support to your MockspressoBuilder()
entry-point
fun MockspressoBuilder(): MockspressoBuilder = com.episode6.mockspresso2.MockspressoBuilder()
.makeRealObjectsUsingPrimaryConstructor()
+ .fallbackWithMockk() // or fallbackWithMockito()
JSR-330 & Dagger2 support
Mockspresso provides plugin modules to support javax.inject/dagger2 constructor, field & method injection using either plugins-javax-inject
and/or plugins-dagger2
.
dependencies {
api "com.episode6.mockspresso2:plugins-javax-inject:$mxoVersion"
// AND / OR
api "com.episode6.mockspresso2:plugins-dagger2:$mxoVersion"
}
Instruct your default MockspressoBuilder()
to require @Inject
annotations on constructors and to apply field and method injection when constructing real objects.
fun MockspressoBuilder(): MockspressoBuilder = com.episode6.mockspresso2.MockspressoBuilder()
- .makeRealObjectsUsingPrimaryConstructor()
+ .makeRealObjectsUsingJavaxInjectRules() // or makeRealObjectsUsingDagger2Rules()
.fallbackWithMockk()
Note: Dagger2Rules
is a super-set of JavaxInjectRules
that adds support for constructors with the @AssistedInject
annotation.
The plugins-javax-inject
module also includes the MockspressoInstance.injectNow(Any)
plugin to inject any pre-existing object with field / method injection. Than can be helpful in android development when running robolectric tests on Activities, Services, etc. that must be created by the system.
Automatic Provider, Lazy and AssistedFactory handling
Included in the plugins-javax-inject
and plugins-dagger2
modules are plugins to automatically map java.inject.Provider<T>
and dagger.Lazy<T>
to their underlying dependencies.
// dagger2 example
fun MockspressoBuilder(): MockspressoBuilder = com.episode6.mockspresso2.MockspressoBuilder()
.makeRealObjectsUsingDagger2Rules()
+ .javaxProviderSupport() // provided by plugins-javax-inject module
+ .dagger2LazySupport() // provided by plugins-dagger2 module
.fallbackWithMockk()
Interfaces annotated with @dagger.AssistedFactory
can also be handled automatically using an additional plugin provided by com.episode6.mockspresso2:plugins-mockito-factories
.
// dagger2 example
fun MockspressoBuilder(): MockspressoBuilder = com.episode6.mockspresso2.MockspressoBuilder()
.makeRealObjectsUsingDagger2Rules()
.javaxProviderSupport()
.dagger2LazySupport()
+ .autoFactoriesByAnnotation<AssistedFactory>() // provided by plugins-mockito-factories module
.fallbackWithMockk()
Note: The plugins-mockito-factories
module requires mockito be included in the project, but does not require your tests know or care about it. It should work side-by-side with mockk but is only applicable in jvm projects.
Integration with testing frameworks
Mockspresso is totally agnostic to testing frameworks. Ensuring and tearing down mockspresso instances isn’t even required for tests (ensuring will be done lazily and teardown callbacks will simply be omitted). However it’s a best practice (especially in large projects) to integrate mockspresso’s life-cycle with your test-framework’s to ensure setup and teardown callbacks all fire at expected times.
We currently offer support plugins plugins-junit4
and plugins-junit5
to assist with this.
dependencies {
api "com.episode6.mockspresso2:plugins-junit4:$mxoVersion"
// OR
api "com.episode6.mockspresso2:plugins-junit5:$mxoVersion"
}
JUnit 4 Rule
@get:Rule val mxo = BuildMockspresso().build()
.junitRule() // returns an object that implements both
// Mockspresso and ClassRule interfaces
JUnit 5 Extension
@RegisterExtension val mxo = BuildMockspresso().build()
.junitExtension() // returns an object that implements both
// Mockspresso and Extension interfaces
Get started writing tests
See the Getting Started doc to start writing tests.