I want to mock my service class and call any methods that it inherits from abstract class and interface like they belong to the service. Unfortunately, when I mock service and call methods from abstract class, then mockito calls real methods in abstract class. Is it possible somehow to fully mock service class?
Interface:
interface MessageProducer<T> {
fun sendMessage(data: T)
}
Abstract class:
abstract class AuditableMessage<T>(
private val auditService: AuditService
) : MessageProducer<T> {
protected abstract val auditPoint: String
fun sendAuditJsonMessage(data: T) {
auditService.auditJson(auditPoint, data as Any)
sendMessage(data)
}
)
Concerete Spring Service
@Service
class ClientProducer(
private val kafkaProducer: KafkaTemplate<String, String>,
auditService: AuditService
) : AuditableMessage<String>(auditService) {
override val auditPoint: String = "MY_AUDIT_POINT"
override fun sendMessage(data: String) {
kafkaProducer.sendDefault(data)
}
}
Test Class
@ExtendWith(MockitoExtension::class)
internal class ClientRequestServiceTest {
@Mock
lateinit var clientProducer: clientProducer
@InjectMocks
lateinit var clientRequestService: ClientRequestService
@Captor
lateinit var requestCaptor: ArgumentCaptor<String>
@Test
fun `test createClient creates request and calls send message`() {
...
clientRequestService.createClient(clientData)
verify(clientProducer).sendAvroAuditJsonMessage(capture(requestCaptor))
}
}
Update test case: I have a default service that injects ClientProducer and calls its method.
@Service
class ClientRequestService(
private val primeClientProducer: clientProducer
) {
fun createClient(clientData: PrimeAddClientInput) {
try {
clientProducer.sendAvroAuditJsonMessage("TEST")
} catch (e: Exception) {
log.error {""}
throw e
}
}
@ExtendWith(MockitoExtension::class)
internal class ClientRequestServiceTest {
@Mock
lateinit var primeClientProducer: PrimeClientProducer
@InjectMocks
lateinit var clientRequestService: ClientRequestService
@Captor
lateinit var requestCaptor: ArgumentCaptor<String>
@Test
fun `test createClient creates request and calls send message`() {
val clientData = easyRandom.nextObject(String::class.java)
clientRequestService.createClient(clientData)
verify(primeClientProducer).sendAvroAuditJsonMessage(capture(requestCaptor))
val request = requestCaptor.value
verify("TEST", request)
}
}
Exception:
java.lang.NullPointerException
at code.AuditService.auditJson$default(AuditService.kt:41)
at code.AuditableMessage.sendAvroAuditJsonMessage(AuditableMessage.kt:23)
at code.ClientRequestService.createClient(ClientRequestService.kt:20)
So it basically calls auditService.auditJson(...) but it shouldn't