[英]Creating an annotation for JUnit 4/5 to initialize and inject an object in tests
I am developing a testing library for Kafka, Kafkaesque .我正在为 Kafka 开发一个测试库, Kafkaesque 。 The library lets you develop integration tests for Kafka using a fluid and elegant (?!) API.该库允许您使用流畅且优雅的 (?!) API 为 Kafka 开发集成测试。 For now, I develop the version for Spring Kafka.现在,我为 Spring Kafka 开发版本。
The library needs to be initialized in every test:该库需要在每次测试中初始化:
@Test
void consumeShouldConsumeMessagesProducesFromOutsideProducer() {
kafkaTemplate.sendDefault(1, "data1");
kafkaTemplate.sendDefault(2, "data2");
new SpringKafkaesque(broker)
.<Integer, String>consume()
.fromTopic(CONSUMER_TEST_TOPIC)
.waitingAtMost(1L, TimeUnit.SECONDS)
.waitingEmptyPolls(5, 100L, TimeUnit.MILLISECONDS)
.withDeserializers(new IntegerDeserializer(), new StringDeserializer())
.expecting()
.havingRecordsSize(2)
.assertingThatPayloads(Matchers.containsInAnyOrder("data1", "data2"))
.andCloseConsumer();
}
Instead of manually initializing the SpringKafkaesque
object, I want to create an annotation that does the magic for me.我不想手动初始化SpringKafkaesque
对象,而是想创建一个对我SpringKafkaesque
的注释。 Something like the @EmbeddedKafka
annotation of Spring Kafka.类似于 Spring Kafka 的@EmbeddedKafka
注释。
@SpringBootTest(classes = {TestConfiguration.class})
@Kafkaesque(
topics = {SpringKafkaesqueTest.CONSUMER_TEST_TOPIC, SpringKafkaesqueTest.PRODUCER_TEST_TOPIC})
class SpringKafkaesqueTest {
@Autowired
private Kafkaesque kafkaesque;
@Test
void consumeShouldConsumeMessagesProducesFromOutsideProducer() {
kafkaTemplate.sendDefault(1, "data1");
kafkaTemplate.sendDefault(2, "data2");
kafkaesque
.<Integer, String>consume()
.fromTopic(CONSUMER_TEST_TOPIC)
.waitingAtMost(1L, TimeUnit.SECONDS)
.waitingEmptyPolls(5, 100L, TimeUnit.MILLISECONDS)
.withDeserializers(new IntegerDeserializer(), new StringDeserializer())
.expecting()
.havingRecordsSize(2)
.assertingThatPayloads(Matchers.containsInAnyOrder("data1", "data2"))
.andCloseConsumer();
}
Is it possible?是否可以? Any suggestion?有什么建议吗?
One possible solution is to create a custom annotation processing using reflection.一种可能的解决方案是使用反射创建自定义注释处理。 You can get the test method name with @Rule
, so for example:您可以使用@Rule
获取测试方法名称,例如:
public class CustomAnnotationTest {
private SpringKafkaesque kafkaesqueInstance;
@Rule
public TestName testName = new TestName();
@Before
public void init() {
Method method = null;
try {
method = this.getClass().getMethod(testName.getMethodName());
} catch (Exception ex) {
// handle exceptions
}
if (method.isAnnotationPresent(EmbeddedKafka.class)) {
// Init your SpringKafkaesque instance here
// kafkaesqueInstance = new SpringKafkaesque(broker)
//
}
}
@EmbeddedKafka
@Test
public void testCustomAnnotated() {
// your test here
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface EmbeddedKafka {
}
}
You need to store this instance in the class-level variable.您需要将此实例存储在类级变量中。 For the methods with no @EmbeddedKafka
annotation, this variable will be null
.对于没有@EmbeddedKafka
注释的方法,此变量将为null
。
With JUnit 5 you may consider using parameter injection with ParameterResolver
.使用 JUnit 5,您可以考虑将参数注入与ParameterResolver
。 First of all, you need to implement this interface:首先需要实现这个接口:
public class KafkaesqueResolver implements ParameterResolver {
@Override
public boolean supportsParameter(ParameterContext parameterContext,
ExtensionContext extensionContext) throws ParameterResolutionException {
return parameterContext.getParameter().getType() == SpringKafkaesque.class;
}
@Override
public Object resolveParameter(ParameterContext parameterContext,
ExtensionContext extensionContext) throws ParameterResolutionException {
// Create an instance of SpringKafkaesque here and return it
return new SpringKafkaesque();
}
}
Next, add @ExtendWith(KafkaesqueResolver.class)
annotation to your test class, and add a parameter to your test method, where you need the instance of SpringKafkaesque
:接下来,将@ExtendWith(KafkaesqueResolver.class)
注释添加到您的测试类,并向您的测试方法添加一个参数,其中您需要SpringKafkaesque
的实例:
@ExtendWith(KafkaesqueResolver.class)
public class ParamInjectionTest {
@Test
public void testNoParams() {
// nothing to inject
}
@Test
public void testWithParam(SpringKafkaesque instance) {
// do what you need with your instance
}
}
No custom annotation required in this case.在这种情况下不需要自定义注释。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.