I was writing an integration test where I am using the same instance of SparkConsumer
for all the tests using @BeforeAll
.
However, between every test, I want to pass different instances of the mocks with @BeforeEach
that are injected in the constructor of SparkConsumer
without making the internals of SparkConsumer
mutable.
The simpler solution I could think of is to pass a proxy instance to the constructor which could watch the current mock instance.
I can use the Delegation feature of Kotlin, but I have concluded that it's only made for delegating to an instance known at initialization.
I made three attempts during my research:
Option A - by Anonymous instance, it works but it's not elegant
SUT = SparkConsumer(PORT, object : IEventsService { override fun create(eventRequest: Event.Request) = eventsServiceMock.create(eventRequest) })
Option B - by a reference to the lateinit var: It evaluates immediately, and fails
SUT = SparkConsumer(PORT, object : IEventsService by eventsServiceMock {})
Option C - by a Delegate property referencing the lateinit var: It evaluates the property immediately, and fails
private val eventsServiceMockByLazy: IEventsService by object { operator fun getValue(thisRef: Any?, property: KProperty<*>): IEventsService = eventsServiceMock } SUT = SparkConsumer(PORT, object : IEventsService by eventsServiceMockByLazy {})
Here is some of the code:
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class SparkConsumerIntegrationTest {
val PORT = 28411
private lateinit var SUT: SparkConsumer
private lateinit var eventsServiceMock: IEventsService
private val eventsServiceMockByLazy: IEventsService by object { // For Option C only
operator fun getValue(thisRef: Any?, property: KProperty<*>): IEventsService = eventsServiceMock
}
@BeforeAll
fun beforeAll() {
// Option A
SUT = SparkConsumer(PORT, object : IEventsService {
override fun create(eventRequest: Event.Request)
= eventsServiceMock.create(eventRequest)
})
// Option B
SUT = SparkConsumer(PORT, object : IEventsService by eventsServiceMock {})
// Option C
SUT = SparkConsumer(PORT, object : IEventsService by eventsServiceMockByLazy {})
}
@AfterAll
fun afterAll() {
SUT.kill()
}
@BeforeEach
fun setUp() {
eventsServiceMock = mock { }
}
@Test
fun `should events-create pass`() {
// S
val requestObj = Event.Request("Some device", "Some statement")
eventsServiceMock.stub {
on {
create(Event.Request("Some device", "Some statement"))
}.doReturn(Event.Data("0123", "Some device", "Some statement"))
}
// ...
}
// ...
}
Is there a nice way to use the Class Delegation feature on an instance by reference / by function result in Kotlin?
i.e. Something like:
SparkConsumer(PORT, object : IEventsService by this::eventsServiceMock {})