0

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

1 Answers1

0

I got some missmatches in dependencies. Now it works correctly