title: How to test ListenableFuture Callbacks in spock
body: <p>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 <a href="https://stackoverflow.com/a/61113581/13258992">here</a>
  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.</p>
  
  <pre><code>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&lt;String, String&gt; 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&lt;SendResult&lt;String, String&gt;&gt; future = kafkaTemplate.send(topicName, message);
          future.addCallback(new ListenableFutureCallback&lt;SendResult&lt;String, String&gt;&gt;() {
  
              @Override
              public void onSuccess(SendResult&lt;String, String&gt; 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)
              }
          });
      }
  }
  
  </code></pre>
  
  <p>and here's the tests code</p>
  
  <pre><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&lt;String, String&gt; kafkaTemplate;
      private KafkaService kafaService;
      private SendResult&lt;String, String&gt; sendResult;
      private SettableListenableFuture&lt;SendResult&lt;?, ?&gt;&gt; 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&lt;&gt;();
          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() &gt;&gt; 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) &gt;&gt; future
          // test success of failed callbacks
      }
  }
  </code></pre>
  
  <p>I've tried this following articles and got me nowhere, I might be misunderstand to usage of this tool.</p>
  
  <ul>
  <li><a href="https://stackoverflow.com/a/56677098/13258992">https://stackoverflow.com/a/56677098/13258992</a></li>
  <li><a href="https://stackoverflow.com/a/56677098/13258992">https://stackoverflow.com/a/56677098/13258992</a></li>
  <li><a href="https://www.baeldung.com/mockito-callbacks" rel="nofollow noreferrer">https://www.baeldung.com/mockito-callbacks</a></li>
  <li><a href="https://www.javatips.net/api/org.springframework.util.concurrent.successcallback" rel="nofollow noreferrer">https://www.javatips.net/api/org.springframework.util.concurrent.successcallback</a></li>
  </ul>
  
  <p><strong>UPDATE: PARTAILLY WORKING</strong></p>
  
  <p>I was able to hit the <code>onSuccess</code> and <code>onFailure</code> on the callback by using
  <code>future.set(sendResult)</code> and <code>future.setException(new Throwable())</code> respectively (thanks to @GarryRussell answer <a href="https://stackoverflow.com/a/57478836/13258992">here</a>). but the problem is verifying the behavior on the <code>onSuccess</code> and <code>onFailure</code> method. for <strong>example</strong> 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.</p>
  
  <pre><code>
      def "Test success send message method"() {
          given:
          sendResult.getRecordMetadata() &gt;&gt; recordMetadata
          future.set(sendResult)
  
          when:
          kafkaService.sendMessage(topicName, message)
  
          then:
          1 * kafkaTemplate.send(_ as String, _ as String) &gt;&gt; future
          1 * logService.create(_) &gt;&gt; {arguments -&gt;
              final LogDto logDto = arguments.get(0)
              // this assert below should fail
              assert logDto.getStatus() == LogStatus.FAILED 
          }
      }
  </code></pre>
  
  <p>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 <code>onSuccess</code> and <code>onFailure</code> callback methods. </p>