1

I have the below class which is working Fine .I have written Junit which in the below objectMapper.writeValueAsString(producerRecord.value() . My Junit starts working fine

  1. If i am remove the executor service submit my Junit starts working fine.
  2. OR if if i add ObjectMapper m = new ObjectMapper();m.writeValueAsString(e); in my Junit strangely my test starts working fine even with ExecutorService .I don't understand why the solution works.

How can i make the Junitwork fine with ExecutorService submit and without the the 2nd point "hack:

private final ExecutorService executorService = Executors.newSingleThreadExecutor();

public void sendMessage(List<Employee> empList) {

    ObjectMapper objectMapper = new ObjectMapper();
    

    for (Employee emp : empList) {

        ListenableFuture<SendResult<String, Employee>> listenableFuture = kafkaTemplate.send(topic,emp );

        listenableFuture.addCallback(new ListenableFutureCallback<SendResult<String, Employee>>() {

            @Override
            public void onSuccess(SendResult<String, Employee> result) {
                
                
                executorService.submit(() -> saveResultInDatabase(result.getProducerRecord());

            }

            //onFailure ommiteed for brevity

            private void saveResultInDatabase(ProducerRecord<String, Employee> producerRecord)
                EmpObj e= new EmpObj();

                e.setSalary(producerRecord.value().getSalary());

                
                try {
                    System.out.println(" in here 1"); // JUNIT  reaches here and stops
                     // objectMapper.writeValueAsString(producerRecord.value() is not run and doesn't throw any error 
                    e.setMsg(objectMapper.writeValueAsString(producerRecord.value()));
                    System.out.println(" in here 2"); // JUNIT never reaches here

                } catch (Exception e) {
                    // JUNIT never reaches here
                    System.out.println(" in here 3");
                    
                    

                }
                // JUNIT never reaches here
                System.out.println(" in here 4");

My Junit is here

Employee e = new Employee();
        List<Employee> employeeList = new ArrayList<>(); 
        employeeList .add(e);
        
        
        ListenableFuture<SendResult<String, Employee>> responseFuture = mock(ListenableFuture.class);
        SendResult<String, Employee> sendResult = mock(SendResult.class);
         ProducerRecord<String, Employee> producerRecord = mock(ProducerRecord.class);
         
         when(kafkaTemplate.send(null,e)).thenReturn(responseFuture);
            when(sendResult.getProducerRecord()).thenReturn(producerRecord);
            when(producerRecord.value()).thenReturn(e);
            
            doAnswer(invocationOnMock -> {
                ListenableFutureCallback<SendResult<String, Employee>> listenableFutureCallback = invocationOnMock.getArgument(0);
                listenableFutureCallback.onSuccess(sendResult);
               
                return null;
            }).when(responseFuture).addCallback(any(ListenableFutureCallback.class));
            
            myKafkaService.sendMessage(employeeList); //invocation to my real method
hello world
  • 171
  • 3
  • 13
  • 1
    That might depend on the kind of executor and so on. One potential starting point: it often helps to actually throw out the multi threading for unit tests. See https://stackoverflow.com/questions/6581188/is-there-an-executorservice-that-uses-the-current-thread for example. Esp. when using an executor service, it is rather simple to have everything happening on the same thread, which makes a lot (not all) tests much easier. – GhostCat Mar 11 '21 at 10:55
  • i can't remove `private final ExecutorService executorService = Executors.newSingleThreadExecutor();`.I execute a database call in the another thread – hello world Mar 11 '21 at 10:58
  • Look into dependency injection. Mockito has the @ InjectMocks annotation, and there is always the possibility to have a package protected ctor that **takes** those fields you want to *set* within your test environment. – GhostCat Mar 11 '21 at 11:37
  • 1
    @I am able to solve it .I injected ExecutorService as deependeny then run the Junit in the same thread by using one of threads here [https://stackoverflow.com/questions/6581188/is-there-an-executorservice-that-uses-the-current-thread] `when(executorServiceFactory.singleThreadedExecutor()).thenReturn(currentThreadExecutorService());` – hello world Mar 11 '21 at 11:40

0 Answers0