GH-1175: Add @SpringRabbitTest

Resolves https://github.com/spring-projects/spring-amqp/issues/1175

- provision boilerplate infrastructure

* Fix test name in doc

* Remove `@ContextConfiguration` from doc.
This commit is contained in:
Gary Russell
2020-03-13 11:15:24 -04:00
committed by GitHub
parent e8264283c8
commit f85a3849fc
12 changed files with 474 additions and 125 deletions

View File

@@ -0,0 +1,82 @@
/*
* Copyright 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.amqp.rabbit.test.context;
import org.springframework.amqp.rabbit.annotation.RabbitBootstrapConfiguration;
import org.springframework.amqp.rabbit.config.AbstractRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.config.DirectRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.junit.BrokerRunningSupport;
import org.springframework.amqp.rabbit.junit.RabbitAvailableCondition;
import org.springframework.amqp.rabbit.test.context.SpringRabbitTest.ContainerType;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.test.context.ContextCustomizer;
import org.springframework.test.context.MergedContextConfiguration;
import org.springframework.util.Assert;
/**
* Adds infrastructure beans to the Spring test context.
*
* @author Gary Russell
* @since 2.3
*
*/
class SpringRabbitContextCustomizer implements ContextCustomizer {
private final SpringRabbitTest springRabbitTest;
SpringRabbitContextCustomizer(SpringRabbitTest test) {
this.springRabbitTest = test;
}
@Override
public void customizeContext(ConfigurableApplicationContext context, MergedContextConfiguration mergedConfig) {
Assert.isInstanceOf(GenericApplicationContext.class, context);
GenericApplicationContext applicationContext = (GenericApplicationContext) context;
BrokerRunningSupport brokerRunning = RabbitAvailableCondition.getBrokerRunning();
CachingConnectionFactory cf;
if (brokerRunning != null) {
cf = new CachingConnectionFactory(brokerRunning.getConnectionFactory());
}
else {
cf = new CachingConnectionFactory(this.springRabbitTest.host(), this.springRabbitTest.port());
cf.setUsername(this.springRabbitTest.user());
cf.setPassword(this.springRabbitTest.password());
}
applicationContext.registerBean("autoConnectionFactory", CachingConnectionFactory.class, () -> cf);
applicationContext.registerBean("autoRabbitTemplate", RabbitTemplate.class, () -> new RabbitTemplate(cf));
applicationContext.registerBean("autoRabbitAdmin", RabbitAdmin.class, () -> new RabbitAdmin(cf));
AbstractRabbitListenerContainerFactory<?> factory;
if (this.springRabbitTest.containerType().equals(ContainerType.simple)) {
factory = new SimpleRabbitListenerContainerFactory();
}
else {
factory = new DirectRabbitListenerContainerFactory();
}
factory.setConnectionFactory(cf);
applicationContext.registerBean("autoContainerFactory", AbstractRabbitListenerContainerFactory.class,
() -> factory);
new RabbitBootstrapConfiguration().registerBeanDefinitions(null,
(BeanDefinitionRegistry) applicationContext.getBeanFactory());
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.amqp.rabbit.test.context;
import java.util.List;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.test.context.ContextConfigurationAttributes;
import org.springframework.test.context.ContextCustomizer;
import org.springframework.test.context.ContextCustomizerFactory;
/**
* The {@link ContextCustomizerFactory} implementation to produce a
* {@link SpringRabbitContextCustomizer} if a {@link SpringRabbitTest} annotation
* is present on the test class.
*
* @author Gary Russell
*
* @since 2.3
*
*/
class SpringRabbitContextCustomizerFactory implements ContextCustomizerFactory {
@Override
public ContextCustomizer createContextCustomizer(Class<?> testClass,
List<ContextConfigurationAttributes> configAttributes) {
SpringRabbitTest test =
AnnotatedElementUtils.findMergedAnnotation(testClass, SpringRabbitTest.class);
return test != null ? new SpringRabbitContextCustomizer(test) : null;
}
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.amqp.rabbit.test.context;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.amqp.rabbit.junit.RabbitAvailable;
/**
* Adds infrastructure beans to a Spring test context; do not use with Spring Boot since
* it has its own auto configuration mechanism.
*
* @author Gary Russell
* @since 2.3
*
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface SpringRabbitTest {
/**
* Container type.
*/
enum ContainerType {
simple, direct
}
/**
* Set the host when not using {@link RabbitAvailable}.
* @return the host.
*/
String host() default "localhost";
/**
* Set the port when not using {@link RabbitAvailable}.
* @return the port.
*/
int port() default 5672;
/**
* Set the user when not using {@link RabbitAvailable}.
* @return the user.
*/
String user() default "guest";
/**
* Set the password when not using {@link RabbitAvailable}.
* @return the password.
*/
String password() default "guest";
/**
* Set the container type to determine which container factory to configure.
* @return the type.
*/
ContainerType containerType() default ContainerType.simple;
}

View File

@@ -0,0 +1,4 @@
/**
* Provides classes relating to the test application context.
*/
package org.springframework.amqp.rabbit.test.context;

View File

@@ -0,0 +1,3 @@
# Spring Test ContextCustomizerFactories
org.springframework.test.context.ContextCustomizerFactory=\
org.springframework.amqp.rabbit.test.context.SpringRabbitContextCustomizerFactory

View File

@@ -0,0 +1,70 @@
/*
* Copyright 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.amqp.rabbit.test.context;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.config.AbstractRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.junit.RabbitAvailable;
import org.springframework.amqp.rabbit.junit.RabbitAvailableCondition;
import org.springframework.amqp.rabbit.listener.RabbitListenerEndpointRegistry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
/**
* @author Gary Russell
* @since 2.3
*
*/
@RabbitAvailable
@SpringJUnitConfig
@SpringRabbitTest
public class SpringRabbitTestTests {
@Autowired
private RabbitTemplate template;
@SuppressWarnings("unused")
@Autowired
private RabbitAdmin admin;
@SuppressWarnings("unused")
@Autowired
private AbstractRabbitListenerContainerFactory<?> factory;
@SuppressWarnings("unused")
@Autowired
private RabbitListenerEndpointRegistry registry;
@Test
void testAutowiring() {
assertThat(((CachingConnectionFactory) template.getConnectionFactory()).getRabbitConnectionFactory())
.isSameAs(RabbitAvailableCondition.getBrokerRunning().getConnectionFactory());
}
@Configuration
public static class Config {
}
}