I asked a question a few days ago regarding stubbing the future response from the kafka.send() method. this was answered and explained correctly by @kriegaex here
Though I faced another issue, on how can i test the onSuccess and onFailure callbacks of this future response. here's the code under testing.
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.support.SendResult;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureCallback;
public class KakfaService {
private final KafkaTemplate<String, String> kafkaTemplate;
private final LogService logService;
public KakfaService(KafkaTemplate kafkaTemplate, LogService logService){
this.kafkaTemplate = kafkaTemplate;
this.logService = logService;
}
public void sendMessage(String topicName, String message) {
ListenableFuture<SendResult<String, String>> future = kafkaTemplate.send(topicName, message);
future.addCallback(new ListenableFutureCallback<SendResult<String, String>>() {
@Override
public void onSuccess(SendResult<String, String> result) {
LogDto logDto = new LogDto();
logDto.setStatus(StatusEnum.SUCCESS);
logService.create(logDto)
}
@Override
public void onFailure(Throwable ex) {
LogDto logDto = new LogDto();
logDto.setStatus(StatusEnum.FAILED);
logService.create(logDto)
}
});
}
}
and here's the tests code
import com…….KafkaService
import com…….LogService
import org.apache.kafka.clients.producer.RecordMetadata
import org.apache.kafka.common.TopicPartition
import org.springframework.kafka.core.KafkaTemplate
import org.springframework.kafka.support.SendResult
import org.springframework.util.concurrent.ListenableFuture
import org.springframework.util.concurrent.ListenableFutureCallback
import org.springframework.util.concurrent.SettableListenableFuture
import spock.lang.Specification
public class kafaServiceTest extends Specification {
private KafkaTemplate<String, String> kafkaTemplate;
private KafkaService kafaService;
private SendResult<String, String> sendResult;
private SettableListenableFuture<SendResult<?, ?>> future;
private RecordMetadata recordMetadata
private String topicName
private String message
def setup() {
topicName = "test.topic"
message = "test message"
sendResult = Mock(SendResult.class);
future = new SettableListenableFuture<>();
recordMetadata = new RecordMetadata(new TopicPartition(topicName, 1), 1L, 0L, 0L, 0L, 0, 0);
kafkaTemplate = Mock(KafkaTemplate.class)
logService = Mock(LogService.class)
kafkaSservice = new KafkaSservice(kafkaTemplate, logService);
}
def "Test success send message method"() {
given:
sendResult.getRecordMetadata() >> recordMetadata
ListenableFutureCallback listenableFutureCallback = Mock(ListenableFutureCallback.class);
listenableFutureCallback.onFailure(Mock(Throwable.class))
future.addCallback(listenableFutureCallback)
when:
kafkaService.sendMessage(topicName, message)
then:
1 * kafkaTemplate.send(_ as String, _ as String) >> future
// test success of failed callbacks
}
}
I've tried this following articles and got me nowhere, I might be misunderstand to usage of this tool.
UPDATE: PARTAILLY WORKING
I was able to hit the onSuccess
and onFailure
on the callback by using
future.set(sendResult)
and future.setException(new Throwable())
respectively (thanks to @GarryRussell answer here). but the problem is verifying the behavior on the onSuccess
and onFailure
method. for example I have a log object entity where I save the status (success or failed), assertion on this behavior always returns true. here's the updated test code for the success scenario.
def "Test success send message method"() {
given:
sendResult.getRecordMetadata() >> recordMetadata
future.set(sendResult)
when:
kafkaService.sendMessage(topicName, message)
then:
1 * kafkaTemplate.send(_ as String, _ as String) >> future
1 * logService.create(_) >> {arguments ->
final LogDto logDto = arguments.get(0)
// this assert below should fail
assert logDto.getStatus() == LogStatus.FAILED
}
}
one more thing that I observe is that when I run the code covarage, theres still a red code indication on the closing curly braces for onSuccess
and onFailure
callback methods.
See Question&Answers more detail:
os