GH-3182: Properly reset bean in the MockIntCtx (#3190)
* GH-3182: Properly reset bean in the MockIntCtx Fixes https://github.com/spring-projects/spring-integration/issues/3182 The `MockIntegrationContext.resetBeans()` doesn't really restore a state of endpoint beans: the handle/source is applied only after start for that endpoint * Stop endpoints in the `MockIntegrationContext.resetBeans()` is they are running currently * Start them back only if their `autoStartup == true` * Clear only those beans which names are provided for the `resetBeans()` **Cherry-pick to 5.2.x** * * Ensure that only provided beans are reset
This commit is contained in:
committed by
Gary Russell
parent
2e409aa599
commit
4e4e8db174
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2019 the original author or authors.
|
||||
* Copyright 2017-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -27,6 +27,7 @@ import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.context.Lifecycle;
|
||||
import org.springframework.context.SmartLifecycle;
|
||||
import org.springframework.integration.core.MessageProducer;
|
||||
import org.springframework.integration.core.MessageSource;
|
||||
import org.springframework.integration.endpoint.IntegrationConsumer;
|
||||
@@ -97,6 +98,11 @@ public class MockIntegrationContext implements BeanFactoryAware {
|
||||
.forEach(e -> {
|
||||
Object endpoint = this.beanFactory.getBean(e.getKey());
|
||||
DirectFieldAccessor directFieldAccessor = new DirectFieldAccessor(endpoint);
|
||||
SmartLifecycle lifecycle = null;
|
||||
if (endpoint instanceof SmartLifecycle && ((SmartLifecycle) endpoint).isRunning()) {
|
||||
lifecycle = (SmartLifecycle) endpoint;
|
||||
lifecycle.stop();
|
||||
}
|
||||
if (endpoint instanceof SourcePollingChannelAdapter) {
|
||||
directFieldAccessor.setPropertyValue("source", e.getValue());
|
||||
}
|
||||
@@ -108,9 +114,19 @@ public class MockIntegrationContext implements BeanFactoryAware {
|
||||
else if (endpoint instanceof IntegrationConsumer) {
|
||||
directFieldAccessor.setPropertyValue(HANDLER, e.getValue());
|
||||
}
|
||||
if (lifecycle != null && lifecycle.isAutoStartup()) {
|
||||
lifecycle.start();
|
||||
}
|
||||
});
|
||||
|
||||
this.beans.clear();
|
||||
if (!ObjectUtils.isEmpty(beanNames)) {
|
||||
for (String name : beanNames) {
|
||||
this.beans.remove(name);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.beans.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2019 the original author or authors.
|
||||
* Copyright 2017-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,16 +17,18 @@
|
||||
package org.springframework.integration.test.mock;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
import static org.assertj.core.api.Assertions.fail;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.springframework.integration.test.mock.MockIntegration.mockMessageHandler;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.reactivestreams.Subscriber;
|
||||
|
||||
@@ -34,6 +36,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.integration.annotation.EndpointId;
|
||||
import org.springframework.integration.annotation.Poller;
|
||||
import org.springframework.integration.annotation.ServiceActivator;
|
||||
import org.springframework.integration.channel.DirectChannel;
|
||||
@@ -42,6 +45,7 @@ import org.springframework.integration.config.EnableIntegration;
|
||||
import org.springframework.integration.endpoint.ReactiveStreamsConsumer;
|
||||
import org.springframework.integration.expression.ValueExpression;
|
||||
import org.springframework.integration.handler.ExpressionEvaluatingMessageHandler;
|
||||
import org.springframework.integration.handler.LoggingHandler;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.integration.test.context.MockIntegrationContext;
|
||||
import org.springframework.integration.test.context.SpringIntegrationTest;
|
||||
@@ -56,7 +60,7 @@ import org.springframework.messaging.SubscribableChannel;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||
|
||||
/**
|
||||
* @author Artem Bilan
|
||||
@@ -64,7 +68,7 @@ import org.springframework.test.context.junit4.SpringRunner;
|
||||
*
|
||||
* @since 5.0
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringJUnitConfig
|
||||
@ContextConfiguration(classes = MockMessageHandlerTests.Config.class)
|
||||
@SpringIntegrationTest
|
||||
@DirtiesContext
|
||||
@@ -97,10 +101,10 @@ public class MockMessageHandlerTests {
|
||||
@Autowired
|
||||
private ArgumentCaptor<Message<?>> messageArgumentCaptor;
|
||||
|
||||
@After
|
||||
@AfterEach
|
||||
public void tearDown() {
|
||||
this.mockIntegrationContext.resetBeans();
|
||||
results.purge(null);
|
||||
this.results.purge(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -181,8 +185,7 @@ public class MockMessageHandlerTests {
|
||||
ArgumentCaptor<Message<?>> messageArgumentCaptor = MockIntegration.messageArgumentCaptor();
|
||||
MessageHandler mockMessageHandler =
|
||||
spy(mockMessageHandler(messageArgumentCaptor))
|
||||
.handleNext(m -> {
|
||||
});
|
||||
.handleNext(m -> { });
|
||||
|
||||
String endpointId = "rawHandlerConsumer";
|
||||
this.mockIntegrationContext.substituteMessageHandlerFor(endpointId, mockMessageHandler);
|
||||
@@ -201,25 +204,22 @@ public class MockMessageHandlerTests {
|
||||
|
||||
this.mockIntegrationContext.resetBeans(endpointId);
|
||||
|
||||
mockMessageHandler =
|
||||
MessageHandler mockMessageHandler2 =
|
||||
mockMessageHandler()
|
||||
.handleNextAndReply(m -> m);
|
||||
|
||||
try {
|
||||
this.mockIntegrationContext.substituteMessageHandlerFor(endpointId, mockMessageHandler);
|
||||
fail("IllegalStateException expected");
|
||||
}
|
||||
catch (Exception e) {
|
||||
assertThat(e).isInstanceOf(IllegalStateException.class);
|
||||
assertThat(e.getMessage()).contains("with replies can't replace simple MessageHandler");
|
||||
}
|
||||
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() ->
|
||||
this.mockIntegrationContext.substituteMessageHandlerFor(endpointId, mockMessageHandler2))
|
||||
.withMessageContaining("with replies can't replace simple MessageHandler");
|
||||
|
||||
this.mockIntegrationContext.resetBeans();
|
||||
|
||||
assertThat(TestUtils.getPropertyValue(endpoint, "handler", MessageHandler.class))
|
||||
.isNotSameAs(mockMessageHandler);
|
||||
.isNotSameAs(mockMessageHandler2);
|
||||
assertThat(TestUtils.getPropertyValue(endpoint, "subscriber", Subscriber.class))
|
||||
.isNotSameAs(mockMessageHandler);
|
||||
.isNotSameAs(mockMessageHandler2);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -238,6 +238,37 @@ public class MockMessageHandlerTests {
|
||||
assertThat(list.size()).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private MessageChannel logChannel;
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testMockIntegrationContextReset() {
|
||||
MockMessageHandler mockMessageHandler = mockMessageHandler();
|
||||
mockMessageHandler.handleNext(message -> { });
|
||||
|
||||
this.mockIntegrationContext.substituteMessageHandlerFor("logEndpoint", mockMessageHandler);
|
||||
|
||||
String endpointId = "mockMessageHandlerTests.Config.myService.serviceActivator";
|
||||
this.mockIntegrationContext.substituteMessageHandlerFor(endpointId, mockMessageHandler);
|
||||
|
||||
this.logChannel.send(new GenericMessage<>(1));
|
||||
|
||||
this.mockIntegrationContext.resetBeans("logEndpoint");
|
||||
|
||||
this.logChannel.send(new GenericMessage<>(2));
|
||||
|
||||
verify(mockMessageHandler).handleMessage(any(Message.class));
|
||||
|
||||
assertThat(TestUtils.getPropertyValue(this.mockIntegrationContext, "beans", Map.class)).hasSize(1);
|
||||
|
||||
assertThat(
|
||||
TestUtils.getPropertyValue(
|
||||
this.context.getBean("mockMessageHandlerTests.Config.myService.serviceActivator"), "handler"))
|
||||
.isSameAs(mockMessageHandler);
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableIntegration
|
||||
public static class Config {
|
||||
@@ -301,6 +332,13 @@ public class MockMessageHandlerTests {
|
||||
});
|
||||
}
|
||||
|
||||
@Bean
|
||||
@EndpointId("logEndpoint")
|
||||
@ServiceActivator(inputChannel = "logChannel")
|
||||
public MessageHandler logHandler() {
|
||||
return new LoggingHandler(LoggingHandler.Level.FATAL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user