У меня есть приложение spring-cloud-stream с привязкой kafka. Я хотел бы создать Test Junit.
У меня есть определения моего класса, такие как ниже: -
@EnableBinding(Sink.class)
@Slf4j
public class Messaging {
@Autowired
private RestTemplate restTemplate;
@Value("${messaging}")
private String url;
@Value("${messaging.prefix}")
private String messaging;
@StreamListener(Sink.INPUT)
public void handle(Message<String> request) {
log.info("Topic name ==> %s :", request.getPayload());
try {
String jsonString = request.getPayload().replace("\\", "").replace("\"{", "{").replace("}\"", "}");
JsonObject jsonObject = (JsonObject)jsonParser.parse(request.getPayload());
String urlRequest =url.concat(jsonObject.get("targetClass").getAsString()).concat(messaging);
HttpEntity<Object> entity = new HttpEntity<Object>(jsonString, getHeaderMap(request.getHeaders()));
ResponseEntity<String> response = restTemplate.postForEntity(urlRequest, entity, String.class);
} catch (ValidationException validationException) {
log.error("Error de validación: {}", validationException.getMessage());
} catch (Exception e) {
log.error("Error ", e.getMessage());
}
}
У меня есть определения моих каналов, например: -
public interface Sink {
String INPUT = "input";
@Input(Sink.INPUT)
SubscribableChannel input();
}
И это свойства моего приложения для привязки ваших каналов к одной очереди:
spring:
cloud:
bus:
destination:CONFIG
enabled: true
stream:
bindings:
input:
group: input_messaging
contentType: application/json
destination: CONFIG_Test1,CONFIG_Test2
Это тест, который я создал, но он дает следующие ошибки: Вызвано: org.springframework.context.ApplicationContextException : Невозможно запустить ServletWebServerApplicationContext из-за отсутствия bean-компонента ServletWebServerFactory.
@RunWith(SpringRunner.class)
@SpringBootTest
@TestPropertySource("classpath:test.properties")
@EnableConfigurationProperties
@ContextConfiguration(classes = MessagingTestConfig.class)
public class MessagingListenerTest {
@Before
public void setup() {
}
@Test
@SuppressWarnings("unchecked")
public void testReturn() throws Exception {
ConfigurableApplicationContext context = SpringApplication.run(MessagingTest.class,
"--server.port=0",
"--spring.jmx.enabled=false",
"--spring.cloud.stream.bindings.input.contentType=text/plain",
"--spring.cloud.stream.bindings.output.contentType=text/plain");
MessageCollector collector = context.getBean(MessageCollector.class);
Processor processor = context.getBean(Processor.class);
Sink inputChannel = context.getBean(Sink.class);
Message<String> request = MessageBuilder.withPayload("headers").setHeader("topicName", "topic-1").build();
inputChannel.input()
.send(request);
Message<String> message = (Message<String>) collector
.forChannel(processor.output()).poll(1, TimeUnit.SECONDS);
assertThat(message).isNotNull();
assertThat(message.getPayload()).contains("topicName");
context.close();
}
@EnableBinding(Sink.class)
@EnableAutoConfiguration
public class TestProcessor {
@StreamListener(Sink.INPUT)
public Message<String> hundle(Message<String> messageHundle) {
return messageHundle;
}
}
}
Интересно, есть ли и способ проверить мой класс, как это сделать, и спасибо за вашу помощь
Это изменение с использованием последней версии Spring Cloud Stream
package com.common.messaging;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.nio.charset.StandardCharsets;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.stream.binder.test.InputDestination;
import org.springframework.cloud.stream.binder.test.OutputDestination;
import org.springframework.cloud.stream.binder.test.TestChannelBinderConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.integration.config.EnableIntegration;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.web.client.RestTemplate;
import lombok.extern.slf4j.Slf4j;
@EnableIntegration
@Configuration
@TestPropertySource(locations="classpath:/msc-test.properties")
@Slf4j
@RunWith(SpringRunner.class)
@ActiveProfiles("test")
@ContextConfiguration(classes = MessagingListenerTestConfig.class)
@Import(TestChannelBinderConfiguration.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
@DirtiesContext
public class MessagingListenerTest {
@Autowired
private MessagingListener listener;
@Autowired
private InputDestination inputDestination;
@Autowired
private OutputDestination outputDestination;
@Mock
private RestTemplate restTemplate;
private static final String URL = "http://localhost:8080/";
@Before
public void setup() {
restTemplate = mock(RestTemplate.class);
ReflectionTestUtils.setField(listener, "restTemplate", restTemplate);
ResponseEntity<String> mockResponse = new ResponseEntity<>("{}", HttpStatus.ACCEPTED);
when(restTemplate.postForEntity(any(), any(), eq(String.class))).thenReturn(mockResponse);
}
@Test
public void testHundleMessage() {
String expectedUrl = URL;
Message<String> request = MessageBuilder.withPayload("headers").setHeader("topicName", "topic-1").build();
log.info("request Test :", request.getPayload());
//inputDestination.send(new GenericMessage<byte[]>(request.getPayload().getBytes(StandardCharsets.UTF_8)));
listener.handle(request);
//Verificar la recepción de los mensajes
assertThat(outputDestination.receive()).isNotNull();
assertThat(outputDestination.receive().getPayload().toString()).contains("topicName");
//Verificar la url del restTemplate
Mockito.verify(restTemplate, Mockito.times(1)).postForEntity(expectedUrl, any(), eq(String.class));
}
}
, но с учетом этой ошибки, и я не знаю, почему
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(ArrayList.java:653)
at java.util.ArrayList.get(ArrayList.java:429)
at org.springframework.cloud.stream.binder.test.OutputDestination.receive(OutputDestination.java:59)
at org.springframework.cloud.stream.binder.test.OutputDestination.receive(OutputDestination.java:73)
at com.common.messaging.MessagingListenerTest.testHundleMessage(MessagingListenerTest.java:87)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)