在配置中被ImportResource覆盖的主spring bean

时间:2018-12-13 08:44:57

标签: java spring dependency-injection integration-testing

我有一个Spring测试配置类,应该重写xml-config中bean中的现有类。但是我的问题是xml bean覆盖了我的test-config中用primary注释的bean。我尝试用其他名称命名测试豆,但这对我也不起作用。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {CamelJmsTest.TestConfig.class})
public class CamelJmsTest {

    @Configuration
    @ImportResource("classpath:production-beans-camel-jms.xml")
    public static class TestConfig {

    @Primary
    @Bean
    public JmsTemplate jmsTemplate() {
        return new JmsTemplate(new ActiveMQConnectionFactory("", "", ACTIVE_MQ_HOST));
    }

    @Primary
    @Bean // ideally i just want this bean to override the bean imported from the xml config
    public RouteConfigBuilder routeConfig() {
        return RouteConfigBuilder.builder().autoStart(true).build();
    }

    @Primary
    @Bean
    public RouteBuilder routeBuilder(@Value("${amq.endpoint}") String endpoint,
                                                              @Autowired Processor processor) {
        return new RouteBuilder(routeConfig(), "", endpoint, processor);
    }
}

    private static final String ACTIVE_MQ_HOST = "vm://activeMQ";

  @BeforeClass
  public static void setActiveMQ() {
    System.setProperty("amq.endpoint", ACTIVE_MQ_HOST);
  } 

  @Autowired
  JmsTemplate jmsTemplate;
  @Test
  public void postJmsMessage() {

    jmsTemplate.send("queue/test", new MessageCreator() {
        @Override
        public Message createMessage(Session session) throws 
     JMSException {
            return session.createTextMessage("Hello World");
        }
    });

    try {
        for (int i = 0; i < 100; i++) {
            Thread.sleep(100);
        }
    } catch (Exception ignored) {
    }
  }
}

这是相关的xml配置:

<bean id="routeConfig" class="routing.RouteConfigBuilder" init-method="builder">
    <constructor-arg name="redeliveryDelay" value="${<props>.redeliveryDelay}" />
    <constructor-arg name="maximumRedeliveries" value="${<props>.maximumRedeliveries}" />
    <constructor-arg name="autoStart" value="false" />
</bean>

<bean id="routeBuilder" class="routing.RouteBuilder">
    <constructor-arg ref="routeConfig" />
    <constructor-arg name="routeId" value="ROUTE_ID_1"/>
    <constructor-arg name="endpoint" value="${amq.endpoint}" />
    <constructor-arg name="processor" ref="myProcessor" />
</bean>    

这是日志输出。运行测试时:

Overriding bean definition for bean 'routeConfig' with a different 
definition:
  replacing [Root bean: class [null]; scope=; abstract=false; 
  lazyInit=false; autowireMode=3; dependencyCheck=0; 
  autowireCandidate=true; primary=true;
  factoryBeanName=CamelJmsTest.TestConfig; 
  factoryMethodName=routeConfig; initMethodName=null; 
  destroyMethodName=(inferred);
defined in CamelJmsTest]
with [Generic bean: class [RouteConfigBuilder]; scope=; 
 abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0;
  autowireCandidate=true; primary=false; factoryBeanName=null; 
  factoryMethodName=null; initMethodName=builder; 
  destroyMethodName=null;
defined in class path resource [production-beans-camel-jms.xml.xml]]

您可以看到我的测试配置中的主要bean被覆盖,我想在测试中使用我的test-config bean。

我正在使用Spring 4.3.x。

我已经阅读了很多相关的文章,但是没有一个给我答案。任何帮助,将不胜感激。

1 个答案:

答案 0 :(得分:4)

名称更改似乎适用于我的简化版本。

我认为这并不重要,但是Java和XML之间的RouteConfigBuilder和RouteBuilder的构造样式似乎有所不同。

经过4.3.20测试

package com.stackoverflow.q53757986;

import static org.junit.Assert.*;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
import org.springframework.context.annotation.Primary;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import org.springframework.test.context.junit4.rules.SpringClassRule;
import org.springframework.test.context.junit4.rules.SpringMethodRule;

@SuppressWarnings("javadoc")
public class CamelJmsTest {

    static final String ACTIVE_MQ_HOST = "vm://activeMQ?broker.persistent=false";

    /** The Constant SPRING_CLASS_RULE. */
    @ClassRule
    public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();

    /** The spring method rule. */
    @Rule
    public final SpringMethodRule springMethodRule = new SpringMethodRule();

    @BeforeClass
    public static void setActiveMQ() {
        System.setProperty("amq.endpoint", ACTIVE_MQ_HOST);
    }

    @Autowired
    JmsTemplate jmsTemplate;

    @Autowired
    RouteConfigBuilder routeConfig;

    @Autowired
    RouteBuilder routeBuilder;

    @Test
    public void postJmsMessage() {

        assertEquals("java", this.routeConfig.source);
        assertEquals("java", this.routeBuilder.source);

        this.jmsTemplate.send("queue/test", (MessageCreator) session -> session.createTextMessage("Hello World"));

        try {
            for (int i = 0; i < 100; i++) {
                Thread.sleep(100);
            }
        } catch (Exception ignored) {}
    }

    @Configuration
    @ImportResource("classpath:production-beans-camel-jms.xml")
    static class TestConfig {

        @Primary
        @Bean
        public JmsTemplate jmsTemplate() {
            return new JmsTemplate(new ActiveMQConnectionFactory("", "", ACTIVE_MQ_HOST));
        }

        @Primary
        @Bean // ideally i just want this bean to override the bean imported from the xml config
        public RouteConfigBuilder routeConfig2() {
            return new RouteConfigBuilder("java");
        }

        @Primary
        @Bean
        public RouteBuilder routeBuilder2() {
            return new RouteBuilder(routeConfig2(), "java");
        }
    }
    }
<?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns = "http://www.springframework.org/schema/beans"
       xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation = "http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

      <bean id="routeConfig"  class="com.stackoverflow.q53757986.RouteConfigBuilder">
        <constructor-arg name="source" value="xml" />
      </bean>

      <bean id="routeBuilder"  class="com.stackoverflow.q53757986.RouteBuilder">
        <constructor-arg name="routeConfig" ref="routeConfig" />
        <constructor-arg name="source" value="xml" />
      </bean>
    </beans>