Search code examples
javaspring-bootapache-kafkaintegration-testingspring-boot-test

Running the original application from Spring Boot integration test


I have a simple Spring Boot application which reads from Kafka topic and persists the messages to some cache. I would like to add an integration test, which would launch my original application, generate some messages from embedded Kafka, and then assert cache contents.

I'm struggling with the "launch my original application" part. How does one do that from Spring Boot integration test? I've tried doing something like that:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = OriginalApplication.class)
@EmbeddedKafka
public class OriginalApplicationIntegrationTest {

    @Test
    public void test() throws Exception {
    ...
    }
}

But I see no attempts from Spring to launch my original application.


Solution

  • First of all, there are two possible big "areas" that can go wrong:

    • Spring Boot Test Setup
    • Kafka Integration

    I believe the question is around the first part so I'll concentrate on that part.

    For a quick answer: When you put a @SpringBootTest annotation, try to use it without parameters at all. And make sure the test is put in a correct package, it matters. This will turn on the automatic resolution of your application.

    Now I'll try to briefly explain why its important, the topic is really broad and deep.

    1. Spring Boot checks whether the class annotated with @SpringBootConfiguration (its an annotation put on @SpringBootApplication - which is in turn is on your main class) exists in the same package as the integration test ( Lets say, com.abc.myapp.test is where you put a test)
    2. If not found, it goes one package up and checks there (com.abc.myapp). It will do that again and again till the root package however, lets assume the @SpringBootApplication annotated class is in this package. Notice, If this recursive "search" doesn't find @SpringBootApplication annotated class - the test doesn't start. That's why its important to use the package structure offered by spring boot application.

    3. Now when it finds that class it know which packages should be scanned for beans to start the spring boot application. So it tries to find beans according to practices of spring boot (package com.abc.myapp and beneath). It does it again recursively top-to-bottom this time.

    It also runs your starters (autoconfigurations) in this mode.

    So, bottom line:

    Specifying @SpringBootTest without parameters makes spring boot doing its best to mimic the startup of the real application

    If you use it with parameters where you put it a configuration however, it behaves totally differently: Its like saying: "I know where my configurations are, don't try to start everything, here is my configuration, load only it".

    A totally different thing, no recursive searches, no auto-configurations startup, etc.