Search code examples
springspring-bootjunitjunit5spring-boot-test

Spring Boot - Testing - tearDown for a bean


I use @EmbeddedKafka annotation as follows to have a kafka mock:

@ExtendWith(SpringExtension.class)
@SpringBootTest
@EmbeddedKafka(partitions = 1,
    topics = {"topic"},
    brokerProperties = {
        "auto.create.topics.enable=${topics.autoCreate:false}",
        "delete.topic.enable=${topic.delete:true}",
        "broker.id=2"})
public class KafkaUsersTest {
    @Autowired
    private EmbeddedKafkaBroker embeddedKafka;

    @Test
    public void test1() {
        // test something
    }

    @Test
    public void test2() {
        // test something
    }

    ...
}

Now, after The tests finish I'd like to close the embeddedKafka bean. Something like this:

    @AfterAll
    public void tearDown(){
        embeddedKafka.getKafkaServers().forEach(KafkaServer::shutdown);
        embeddedKafka.getKafkaServers().forEach(KafkaServer::awaitShutdown);
    }

The problem is:

  • An @AfterAll method can only be static.
  • If I make it static - then also the embeddedKafka has to be static, and then @Autowired annotation will not work.

I guess I can the bean to a static field from one of the tests and then use it in the tearDown(), but it's really ugly.

What is the "good practice" for closing a bean only once after all tests have completed?


Solution

  • An @AfterAll method can only be static.

    That's not true.

    From the JUnit 5 User Guide:

    Denotes that the annotated method should be executed after all @Test, @RepeatedTest, @ParameterizedTest, and @TestFactory methods in the current class; analogous to JUnit 4’s @AfterClass. Such methods are inherited (unless they are hidden or overridden) and must be static (unless the "per-class" test instance lifecycle is used).

    An @AfterAll method can be non-static if you use @TestInstance(Lifecycle.PER_CLASS). This is also documented in the JUnit 5 User Guide:

    The "per-class" mode has some additional benefits over the default "per-method" mode. Specifically, with the "per-class" mode it becomes possible to declare @BeforeAll and @AfterAll on non-static methods as well as on interface default methods.