-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Single shared KafkaEmbedded is all JUnit tests #666
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
How about this: https://docs.spring.io/spring-kafka/docs/2.1.5.RELEASE/reference/html/_reference.html#__embeddedkafka_annotation ? Although that sounds like you just need a fully blown external Kafka running and that's all. |
@artembilan thank you for suggesting Of course, it is possible to run standalone Kafka server for tests but it is not convenient compared to embedded one. |
You can use a test suite and put the embedded kafka broker there. It's generally not a good idea to use a fixed port in tests since that port might be in use elsewhere on the server; this is particularly a problem on CI servers which might have multiple builds running. However, since it's best to define the topics to the embedded server so that they are created before the tests start, the suite would have to be configured with all the required topics for all the tests. |
@garyrussell thank you for the answer. Hardcoded port in the sample is used for simplicity. Port can be specified as a property: @Value("${embedded.kafka.port:9092}")
private int port;
@Bean
public KafkaEmbedded kafkaEmbedded() {
KafkaEmbedded kafkaEmbedded = new KafkaEmbedded(1, false, 1, "test_topic");
kafkaEmbedded.setKafkaPorts(port);
return kafkaEmbedded;
} To avoid problems on CI with the port conflicts, a random port can be passed as a property:
Usage of a fixed port makes sure that only 1 instance of Kafka server is started. To use random port chosen by Spring either |
@artembilan regarding This annotation with the list of all topics has to be added to every class that requires Kafka. @EmbeddedKafka(topics = {"test_topic", "test_topic2"})
public class KafkaTestBase {
@Autowired
protected KafkaEmbedded kafkaEmbedded;
} The problem is that with
Am I using |
Well, I think there is just no solution for you on the matter. I may suggest you to start a
To be used in target test configurations:
Not sure when ad how to kill such a daemon, but looks like Gradle team checks periodically their daemon activity and eventually it kills itself. Our practice is like do not cache resources between tests - performance in favor of stability. |
Resolves spring-projects#666 Allow a single `KafkaEmbedded` to be used across multiple test classes.
@evgeniy-khist The attached PR seems to fit the bill. |
Resolves spring-projects#666 Allow arbitrary `AdminClient` operations and adding topics. Polishing - PR Comments
@garyrussell A section in the testing.adoc in the attached PR answers my question. Thanks! |
Resolves #666 Allow arbitrary `AdminClient` operations and adding topics. Polishing - PR Comments
Resolves #666 Allow arbitrary `AdminClient` operations and adding topics. Polishing - PR Comments
Resolves spring-projects/spring-kafka#666 Allow arbitrary `AdminClient` operations and adding topics. Polishing - PR Comments
Maybe an overkill, I was facing the same issue, I had created one gradle plugin to manage embedded Kafka for my tests. |
Hi @ashishkujoy ! Thank you for sharing that with us. Really cool feature. Looks like your solution is based on this project https://github.com/embeddedkafka/embedded-kafka, so it might be better to contribute your plugin back there. The only problem that this is limited to Gradle and if you run unit tests from IDE, you still need to come up with some other solution. Nevertheless it is already out of this project scope. |
I found another solution which comes from JUnit 5 Platform Launcher - the
Then you register it as a Java’s We may add this as an out-of-the-box solution with some external See more info in JUnit 5 docs: https://junit.org/junit5/docs/current/user-guide/#launcher-api-listeners-custom |
Thanks, @artembilan, for letting me know about this, |
Fixes spring-projects#666 * Introduce a `GlobalEmbeddedKafkaTestExecutionListener` which is registered by the service loader from JUnit Platform * Make its activation conditional based on the `spring.kafka.global.embedded.enabled` system property * Expose some other configuration properties for the target global `EmbeddedKafkaBroker` * Verify its functionality via manual `Launcher.execute()` * Add more `@DirtiesContext` to some tests in the `spring-kafka-test` which don't close their embedded brokers on the exit
I have decided to go ahead and introduce the mentioned listener as a framework component. |
Fixes spring-projects#666 * Introduce a `GlobalEmbeddedKafkaTestExecutionListener` which is registered by the service loader from JUnit Platform * Make its activation conditional based on the `spring.kafka.global.embedded.enabled` system property * Expose some other configuration properties for the target global `EmbeddedKafkaBroker` * Verify its functionality via manual `Launcher.execute()` * Add more `@DirtiesContext` to some tests in the `spring-kafka-test` which don't close their embedded brokers on the exit
Fixes spring-projects#666 * Introduce a `GlobalEmbeddedKafkaTestExecutionListener` which is registered by the service loader from JUnit Platform * Make its activation conditional based on the `spring.kafka.global.embedded.enabled` system property * Expose some other configuration properties for the target global `EmbeddedKafkaBroker` * Verify its functionality via manual `Launcher.execute()` * Add more `@DirtiesContext` to some tests in the `spring-kafka-test` which don't close their embedded brokers on the exit
* GH-666: Single global embedded Kafka with JUnit 5 Fixes #666 * Introduce a `GlobalEmbeddedKafkaTestExecutionListener` which is registered by the service loader from JUnit Platform * Make its activation conditional based on the `spring.kafka.global.embedded.enabled` system property * Expose some other configuration properties for the target global `EmbeddedKafkaBroker` * Verify its functionality via manual `Launcher.execute()` * Add more `@DirtiesContext` to some tests in the `spring-kafka-test` which don't close their embedded brokers on the exit * * Print local launcher summary into SOUT for tracing the nested problems * * Fix prefix for `file:` resource in the test * * Make `junit-platform-launcher` as provided dep - this is part of JUnit platform the test plan is going to be run * Add missed new line in the end of `junit-platform.properties` * Rethrow an exception from the local launcher in the `GlobalEmbeddedKafkaTestExecutionListenerTests` to fail if its suite test classes have failed. * * Fix JavaDocs for `GlobalEmbeddedKafkaTestExecutionListener` constants * Move system properties clean up in the `GlobalEmbeddedKafkaTestExecutionListenerTests` into `@AfterAll` * Add docs for this new feature * Add `sample-05` to demonstrate global embedded Kafka in action via Maven configuration * * Mention `sample-05` in the common `README.adoc` for samples * * Fix language in the `testing.adoc` * Add new lines into new files * Add `spring.kafka.consumer.auto-offset-reset=earliest` to make a consumer to start from the beginning of the partition: fixes a race condition when publishing happens before consumer is started * Make `mvnw` as an executable * Add `spring.embedded.kafka.brokers.property` explanation into docs * * Fix language in docs Co-authored-by: Gary Russell <[email protected]> * * Make `Sample05Application2Tests` passing * Remove `deliberately failing` sentence from the JavaDoc an README * Clean up unused imports Co-authored-by: Gary Russell <[email protected]>
Facing the same challenge, I was checking the
Where Any advice would be appreciated. Btw, I am using Spring Boot. |
This issue is old enough and resolved some way in mutual agreement. Now about the problem. I understand the convenience of the Or just design your tests if you would deal with real Kafka broker. |
It seems like there is no convenient way to define single shared KafkaEmbedded that will be used in all JUnit tests.
There might be multiple tests that require
KafkaEmbedded
.When
@KafkaEmbedded
is used with@ClassRule
, Kafka server is started and stopped for every test class.It may take a lot of time. Better to have embedded Kafka server started only once for all test classes.
Straightforward approach is to add to test sources configuration class defining a
KafkaEmbedded
bean:The problem is that there might tests creating multiple test contexts:
and
In this example Kafka server will be started twice. Second executed test class will fail with the exception
if port is specified or new Kafka server will be started if random port is used.
Moreover, if
@DirtiesContext
is used, together with the refresh of the test context Kafka server will be restarted.As a workaround
KafkaEmbedded
can be defined as a constant in some base test class that test classes will extend:This way Kafka server will be started in a separate Spring application context that will not be affected by
@DirtiesContext
or multiple test contexts (due to the usage of@AutoConfigureMockMvc
etc.).Can such approach be considered a normal solution or a workaround?
Are there any more efficient ways to have single shared
KafkaEmbedded
instance across all JUnit tests?Sample:
BindException: Address already in use
: https://github.com/evgeniy-khist/spring-kafka-embedded-sampleKafkaEmbedded
a constant of base test class:https://github.com/evgeniy-khist/spring-kafka-embedded-sample/pull/1/files
The text was updated successfully, but these errors were encountered: