Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

unit testing ListenableFuture kafkaTemplate.send always returns null

I'm trying to unit test the callbacks from the kafkaTemplate.send() but its not working as expected. here's the code snippet of the code im trying to test.

    @Override
    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) {
                System.out.print("Success")
            }
            @Override
            public void onFailure(Throwable ex) {
                System.out.print("Failed")
            }
        });
    }

and this is the unit test code


    private KafkaTemplate<String, String> kafkaTemplate;
    private KafkaService kafkaService;
    private SendResult<String, String> sendResult;
    private ListenableFuture<SendResult<String, String>> future;
    private RecordMetadata recordMetadata
    private String topicName
    private String message



    def setup() {
        kafkaTemplate = Mock(KafkaTemplate.class)
        kafkaService = new KafkaService(kafkaTemplate);
        topicName = "test.topic"
        message = "test message"
        sendResult = Mock(SendResult.class);
        future = Mock(ListenableFuture.class);
        recordMetadata = new RecordMetadata(new TopicPartition(topicName, 1), 1L, 0L, 0L, 0L, 0, 0);
    }

    def "Test success send message method"() {
        given:
        sendResult.getRecordMetadata() >> recordMetadata
        kafkaTemplate.send(_ as String, _ as String) >> future

        when:
        kafkaService.sendMessage(topicName, message)

        then:
        // catch success or failed here.

        1 * kafkaTemplate.send(_,_) >> {arguments ->
            final String topicNameParam = arguments.get(0)
            final String messageParam = arguments.get(1)

            assert topicNameParam == topicName
            assert messageParam == message
        }
    }

based on the debugger future is null on this scenario

ListenableFuture<SendResult<String, String>> future = kafkaTemplate.send(topicName, message); // future null
 future.addCallback(new ListenableFutureCallback<SendResult<String, String>>() { // future null

i already read a lot of answers here but it does not solved the issue or havent they explain it well that i would understand where the problem is. like this one https://stackoverflow.com/a/56677098

thanks for the help in advance!

like image 211
ryan Avatar asked Dec 06 '25 07:12

ryan


1 Answers

You are making a typical Spock beginner's mistake when trying to combine mocking and stubbing: First declare a stub result in the given: block and later a checked mock interaction (without stub result) in the then: block. But mocking and stubbing always have to happen in the same interaction as described in the manual chapter I linked to. The manual also explains that the interaction in the then: block wins in your case, i.e. because you do not specify a stub result there, the result will default to null.

Furthermore, you make the argument verification much more difficult than necessary. Just use simple argument constraints instead. Your test will pass if you change it like this:

  def "Test success send message method"() {
    given:
    sendResult.getRecordMetadata() >> recordMetadata
//    kafkaTemplate.send(_ as String, _ as String) >> future

    when:
    kafkaService.sendMessage(topicName, message)

    then:
    // catch success or failed here.
    1 * kafkaTemplate.send(topicName, message) >> future
  }
like image 166
kriegaex Avatar answered Dec 08 '25 22:12

kriegaex



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!