Search code examples
javaspring-bootasynchronousintegration-testing

How to write spring boot unit test for a method which calls another @Async method inside it?


I need to write integration test for "processEvent" method which calls a @Async method inside it. I tried writing a test for this method, but the issue was it did not save the Student object to the DB. However removing @Async annotation allows me to save the object. I want to know how should I write Test cases for this method, eliminating the @Async issue. I want to save the student object while testing. I have attached my code and below.

Here is the ClassA and it has the method I want to test.

@Service
public class ClassA {

private final ConfigurationProcessor<Student> configurationProcessor;

    @Autowired
    public ClassA(ConfigurationProcessor<Student> configurationProcessor) {
        this.configurationProcessor = configurationProcessor;
    }

    public void processEvent(Configuration configuration) {
        configurationProcessor.process(configuration);
    }
} 

This is the interface ConfigurationProcessor class

public interface ConfigurationProcessor<T> {
    void process(Configuration configuration);
}

And this is its Impl class

@Service
public class ConfigurationProcessoeStudents10Impl implements ConfigurationProcessor<Student> {
    private final StudentRepository studentRepository;

    @Autowired
    public ConfigurationProcessoeStudents10Impl(StudentRepository studentRepository) {
        this.studentRepository = studentRepository;
        }
    
    @Override
    @Async
    public void process(Configuration configuration) {
        studentRepository.save(Student.builder().Name(configuration.name).Age(configuration.age));
    }
} 

This is the Test I have written so far.

@EnableAutoConfiguration
@SpringBootTest
public class AudienceC10IT {

  @Autowired
  ClassA classA;
  
  @Test
  @Tag("VerifyProcess")
  @DisplayName("Verify kafka event consumer from configuration manager")
  void verifyProcess(){
    Configuration configuration = new Configuration("lal",12);
    classA.processEvent(configuration);
  }
}
 

Solution

  • If you have have set up a ThreadPoolTaskExecutor bean you can Autowire it in your test. Then, after you call your async method, you can await the termination. Then you can check for the expected behaviour / result.

    Something like this:

    @Autowired
    private ThreadPoolTaskExecutor asyncTaskExecutor;
    
    @Test
    void test() {
        callAsyncMethod();
    
        boolean terminated = asyncTaskExecutor.getThreadPoolExecutor().awaitTermination(1, TimeUnit.SECONDS);
    
        assertAsyncBehaviour();
    
    
    }