简体   繁体   中英

How to override spring bean definition defined in xml with @Configuration class for jerseytest

I have been trying to figure this out for some time but am not able to get it to work. I am using spring version 3.2.3.RELEASE and I think this may be causing some of my issues. My goal is to override the bean defined in the xml with a configuration file that has imported the configuration.The last class listed is my TestAppConfig where I import the AppConfig and want to simply override the bean implementation with mock implementations. However this is not working for me. Any suggestions would be appreciated.

This is my bean definition class where I define a couple of beans.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">

    <import resource="rest-common.xml"/>

    <context:property-placeholder  location="classpath:module.properties"/>


    <bean name="vcheckResource" class="com.foo.vcheck.resources.VcheckResource" />

    <bean name="vcheckProvider" class="com.foo.vcheck.provider.VcheckProvider" />

    <bean name="Vcheck" class="com.foo.vcheck.provider.VcheckMessageRouter" />

</beans>

Here is the production @Configuration class where I import the bean configuration file.

@Configuration
@Import(RestAppConfig.class)
@ImportResource({VcheckAppConfig.ModuleResources})
public class VcheckAppConfig {

    public static final String ModuleResources =  "classpath:bcpbx-api-vcheck-rest-beans.xml";

}

This is my Testing configuration class where I want to override the implementations with my Mockito mocks and in the unit test the production code should be injected with these mock classes. However the beans in the xml configuration are not being overridden for whatever reason. If I remove the import it will use the beans from this class so I know this is working. Is this possible with 3.x version of spring?

@Configuration
@Import(VcheckAppConfig.class)
public class TestAppConfig {

    @Bean
    public Account testAccount() {
        return new Account("TEST_ACCOUNT", new Vendor("TEST_VENDOR"));
    }

    @Bean(name ="vcheckResource")
    public VcheckResource vcheckResource() {
        return new VcheckResource(vcheckProvider(), new UUIDGenerator());
    }

    @Bean(name="vcheckProvider")
    public IVcheckProvider vcheckProvider() {
        System.out.println("CALLIGN GET MOCK");
        return Mockito.mock(VcheckProvider.class);
    }

    @Bean
    public IMessageRouter messageRouter() {
        return Mockito.mock(IMessageRouter.class);
    }

    @Bean
    public ICommandResponseCallbackRegistry responseRegistry() {
        return Mockito.mock(ICommandResponseCallbackRegistry.class);
    }

}

It appears there is no way to do this with spring.

How do I override a Spring bean definition yet still reference the overridden bean?

I converted to use spring-mockito and used another bean xml file to add the mocks. Then import both of the configuration xml files. This works fine with spring mockito in my unit test. I did have to change my version of mockito to use 1.9.0 to be compatable with spring mockito.

https://bitbucket.org/kubek2k/springockito/wiki/Home

@Configuration
@ImportResource({VcheckAppConfig.ModuleResources, TestAppConfig.MockModuleResources})
public class TestAppConfig {

    public static final String MockModuleResources = "classpath:bcpbx-api-vcheck-rest-beans-mock.xml";

    @Bean
    public Account testAccount() {
        return new Account("TEST_ACCOUNT", new Vendor("TEST_VENDOR"));
    }
}

Here is my example mock where I override the implementation for my provider with the simple mock. I was able to

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mockito="http://www.mockito.org/spring/mockito"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.mockito.org/spring/mockito http://www.mockito.org/spring/mockito.xsd">

    <mockito:mock id="vcheckProvider" class="com.foo.vcheck.provider.VcheckProvider"  />

</beans>

As a side note I am going to post this also because it was a nice solution to allow me to do jersey testing with spring dependency injection.

public abstract class AbstractSpring3JerseyTest implements ApplicationContextAware {

    private static final Logger logger = Logger.getLogger(AbstractSpring3JerseyTest.class.getName());

    private JerseyTest jerseyTest;

    private ApplicationContext applicationContext;

    @Before
    public void setup() throws Exception {
        jerseyTest.setUp();
    }

    @After
    public void tearDown() throws Exception {
        jerseyTest.tearDown();
    }

    protected Application configure(ApplicationContext appContext) {
        ResourceConfig resourceConfig = ResourceConfig.forApplication(new RestApplication());
        resourceConfig.property("contextConfig", appContext);
        resourceConfig.register(SpringLifecycleListener.class).register(RequestContextFilter.class);
        resourceConfig.packages(getResourcePackages());
        resourceConfig.register(new RestAuthenticationFilter());
        resourceConfig.property(ServerProperties.RESPONSE_SET_STATUS_OVER_SEND_ERROR, "true");
        resourceConfig.register(new LoggingFilter(logger, 20000));

        return resourceConfig;
    }

    protected abstract String[] getResourcePackages();

    public static void setDebugLevel(Level level) {
        Logger anonymousLogger = LogManager.getLogManager().getLogger("");
        Handler[] handlers = anonymousLogger.getHandlers();
        anonymousLogger.setLevel(level);
        for (Handler h : handlers) {
            if (h instanceof ConsoleHandler)
                h.setLevel(level);
        }
    }

    public final WebTarget target() {
        return jerseyTest.target();
    }

    public final WebTarget target(final String path) {
        return jerseyTest.target().path(path);
    }

    public ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    /**
     * Set the ApplicationContext that this object runs in. Normally this call
     * will be used to initialize the object.
     * <p>
     * Invoked after population of normal bean properties but before an init
     * callback such as
     * {@link org.springframework.beans.factory.InitializingBean#afterPropertiesSet()}
     * or a custom init-method. Invoked after
     * {@link ResourceLoaderAware#setResourceLoader},
     * {@link ApplicationEventPublisherAware#setApplicationEventPublisher} and
     * {@link MessageSourceAware}, if applicable.
     * 
     * @param applicationContext
     *            the ApplicationContext object to be used by this object
     * @throws ApplicationContextException
     *             in case of context initialization errors
     * @throws BeansException
     *             if thrown by application context methods
     * @see org.springframework.beans.factory.BeanInitializationException
     */
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
        jerseyTest = new JerseyTest(configure(applicationContext)) {
        };
    }
}

Here is a simple test just to verify that all of the parts are working.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { TestAppConfig.class } )
public class TestVcheckResourceJersey extends AbstractSpring3JerseyTest {


    @Inject
    IVcheckProvider vcheckProvider;

    @Test
    public void testCheckNpanxx() throws ProviderException {
        Assert.assertNotNull(vcheckProvider);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM