Injecting your test classes

Instead of manually creating your own mocks & fakes, it can be useful to inject them in your test classes, especially if you have multiple tests using them. This page shows how to declare them as annotated properties, and how the processor fills them in.

Injecting into a test class

class MyTests {
    @Mock lateinit var db: Database
    @Mock lateinit var api: API

    @Fake lateinit var user: User

    lateinit var controller: Controller

    val mocker = Mocker()

    @BeforeTest fun setUp() {
        mocker.reset() (1)
        mocker.injectMocks(this) (2)
        controller = ControllerImpl(db, api) (3)
    }

    @Test fun controllerTest() {
        mocker.every { api.getCurrentUser() } returns user
        mocker.every { db.saveUser(isAny()) } returns Unit
        controller.start()
        mocker.verify {
            api.getCurrentUser()
            db.saveUser(user)
        }
    }
}
1 Resets the mocker before any test (which removes all mocked behaviour & logged calls), so that each test gets a "clean" mocker.
2 Injects mocks and fakes.
3 Create classes to be tested with injected mocks & fakes.

As soon as a class T contains a @Mock or @Fake annotated property, a Mocker.injectMocks(receiver: T) function will be created by the processor.

Don’t forget to reset the Mocker in a @BeforeTest method!

Sharing mocks in a base class

Inherited properties are injected as well, so you can put the mocks & fakes that all your tests need in a shared base class:

abstract class BaseTests {
    @Mock lateinit var db: Database (1)

    val mocker = Mocker()

    @BeforeTest fun setUp() {
        mocker.reset()
        mocker.injectMocks(this) (2)
    }
}

class MyTests : BaseTests() {
    @Mock lateinit var api: API
}
1 Declared in the base class, but injected into every subclass.
2 Resolves to injectMocks(receiver: MyTests), which sets both db and api.
The base class must be in the same module as its subclasses: the processor only sees the annotations of the module it is running on.

Injecting other classes

You can inject other classes than test classes:

class MyMocks {
    @Mock lateinit var db: Database
    @Mock lateinit var api: API
}

…​will generate the Mocker.injectMocks(receiver: MyMocks) function.

The test helper removes the Mocker and reset boilerplate of the first example.