I have several heavy Spring integration tests (yeah, it's not the best approach and I'm running out of time to mock all external deps properly)
Here is typical annotation of a test
@ExtendWith(SpringExtension.class)
@AutoConfigureMockMvc
@EmbeddedKafka(
partitions = 1,
brokerProperties = {"log.dir=target/${random.int}/embedded-kafka/data"},
topics = {
"${service.topic}",
"${service.dead-letter-topic}"
})
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class OneOfMyHeavyintegrationTests extends DatabaseBackedTest {
// omitted for brevity
//
}
// foundation for DB in tests
@ContextConfiguration(initializers = DatabaseBackedTest.Initializer.class)
public abstract class DatabaseBackedTest {
private static final EmbeddedPostgresInfo db = EmbeddedPostgresDatabase.create().start();
static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext context) {
TestPropertyValues.of("spring.datasource.url=" + db.getJdbcUrl()).applyTo(context.getEnvironment());
}
}
}
Tests periodically fail due to
22:14:51.462 [main] INFO o.a.k.common.utils.AppInfoParser - Kafka version : 2.0.1
22:14:51.463 [main] INFO o.a.k.common.utils.AppInfoParser - Kafka commitId : fa14705e51bd2ce5
22:14:51.466 [main] WARN o.a.k.common.utils.AppInfoParser - Error registering AppInfo mbean
javax.management.InstanceAlreadyExistsException: kafka.server:type=app-info,id=0
at java.management/com.sun.jmx.mbeanserver.Repository.addMBean(Repository.java:436)
at java.management/com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerWithRepository(DefaultMBeanServerInterceptor.java:1855)
at java.management/com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerDynamicMBean(DefaultMBeanServerInterceptor.java:955)
at java.management/com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerObject(DefaultMBeanServerInterceptor.java:890)
at java.management/com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerMBean(DefaultMBeanServerInterceptor.java:320)
at java.management/com.sun.jmx.mbeanserver.JmxMBeanServer.registerMBean(JmxMBeanServer.java:522)
at org.apache.kafka.common.utils.AppInfoParser.registerAppInfo(AppInfoParser.java:62)
at kafka.server.KafkaServer.startup(KafkaServer.scala:321)
at kafka.utils.TestUtils$.createServer(TestUtils.scala:132)
at kafka.utils.TestUtils.createServer(TestUtils.scala)
There are two questions:
1. what is the right way to make tests co-exist together? I set forkCount=0
in surefire plugin. It seemed to help
mock
/ disable
components before starting tests?2.1. I don't really need to start all my @Scheduled
@Component
during every tests
2.2. I don't really need to start Kafka consumers at every test
Thanks!
If you want to run several tests with kafka you can use DirtiesContext annotation on your test class. this will tell spring that this test does things that might collide with others and needs to be cleaned. you should put it on each class that uses kafka (on this error)
If you have components of your system that you don't need on these tests, use MockBean annotation to replace them with mocks when the server starts