springtestingmockingjavabeanscontext.xml

Replace spring bean in one context with mock version from another context


I'm writing an integration test where an application context xml is initialized during startup. There are several test methods in the test class which make use of a specific bean 'X'(already defined in the xml). My actual requirement is to mock bean X only for one of the test methods.

Inside a test method: I tried creating a separate application context using ClassPathXMLApplicationContext with only the mock bean 'M'.

Now I have two Application Contexts (AC): 1. One created during test case startup (which contains the actual bean X) and 2. One created using ClassPathXMLApplicationContext within the test method (which has the mock bean M).

I want to replaced the actual bean definition 'X' within AC:1, using the mock bean definition 'M' from AC:2.

Can somebody throw some light on this please?


Solution

  • There is not a clear way to replace a a bean in a refreshed ApplicationContext unless you close it and refresh it again.

    To emulate it, the common approach is to use a Proxy of the bean that you want to replace and change the target at runtime.

    You can do it easily using the framework aop support classes:

    <bean id="realBean" class="RealClass" />
    <bean id="mockBean" class="MockClass" />
    <bean id="targetSource" class="org.springframework.aop.target.HotSwappableTargetSource">
        <constructor-arg ref="realBean" />
    </bean>
    
    <bean id="bean" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="targetSource" ref="targetSource" />
    </bean>
    

     

    @Test
    public void testWithMockBean() {
    Object real = targetSource.swap(mock);
    ....
    // do your test work
    ...
    targetSource.swap(real);
    
    }