How does one programmatically create a Spring context?

Try either:

  • Spring JavaConfig
  • Grails BeanBuilder
  • new AtUnit

JavaConfig code sample

@Configuration
public class AppConfig {
    @Bean
    public TransferService transferService() {
        return new TransferServiceImpl();
    }
}

BeanBuilder code sample

def bb = new grails.spring.BeanBuilder()

bb.beans { 
  dataSource(BasicDataSource) { 
    driverClassName = "org.hsqldb.jdbcDriver" 
    url = "jdbc:hsqldb:mem:grailsDB" 
    username = "sa" 
    password = "" 
  } 

  sessionFactory(ConfigurableLocalSessionFactoryBean) { 
    dataSource = dataSource
    hibernateProperties = [ "hibernate.hbm2ddl.auto":"create-drop", "hibernate.show_sql":true ] 
  }   
}

AtUnit code sample

Unit test

@RunWith(AtUnit.class)
@Container(Container.Option.SPRING)
@MockFramework(MockFramework.Option.EASYMOCK)
public class ExampleSpringEasyMockTest {

    @Bean @Unit UserManagerImpl manager;
    @Bean("fred") User fred;
    @Bean("userDao") @Mock UserDao dao;
    @Bean("log") @Stub Logger log;

    @Test
    public void testGetUser() {
        expect(dao.load(1)).andReturn(fred);
        replay(dao);
        assertSame(fred, manager.getUser(1));
        verify(dao);
    }


}

Context file ( private for the test )

<?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-2.0.xsd">

  <bean id="userManager" class="atunit.example.subjects.UserManagerImpl">
      <constructor-arg ref="log"/>
      <property name="userDao" ref="userDao"/>
  </bean>

  <bean id="fred" class="atunit.example.subjects.User">
      <property name="id" value="500"/>
      <property name="username" value="fred"/>
  </bean>

</beans>

Why don't you just use two different contexts? one for production, one for tests... you're going about this the hard way.


In Spring you can override bean definition as easily as making them appear again lower in the file. We use this a lot for the very purpose you described; to have a different bean definition for unit tests than for production.

This is the pattern we use for our test-context.xml

<import resource="classpath:production-context.xml">

<bean id="overriddenBean" class="com.MyClass">
   ....
</bean>

This means that the bean with id = overriddenBean will be wired into the classes in your production contewxts were it is referenced. Allowing you to swap the beans you need for testing in place of those that you need for production code.

Hope this helps