java—为JUnit4/5创建注解,以在测试中初始化和注入对象

fsi0uk1n  于 2021-06-04  发布在  Kafka
关注(0)|答案(1)|浏览(364)

我正在为Kafka开发一个测试库,Kafka。该库允许您使用流畅而优雅的(?)应用程序编程接口。现在,我为SpringKafka开发了一个版本。
每次测试都需要初始化库:

@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();
 }

而不是手动初始化 SpringKafkaesque 对象,我想创建一个注解,为我发挥魔力。类似于 @EmbeddedKafka 《Spring的Kafka》注解。

@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();
   }

有可能吗?有什么建议吗?

voj3qocg

voj3qocg1#

少年4

一种可能的解决方案是使用反射创建自定义注解处理。您可以使用 @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 {
    }
}

您需要将此示例存储在类级别变量中。对于没有 @EmbeddedKafka 注解,此变量将 null .

少年5

对于JUnit5,您可以考虑使用参数注入 ParameterResolver . 首先,您需要实现这个接口:

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();
    }
}

下一步,添加 @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
    }
}

这种情况下不需要自定义注解。

相关问题