在测试类中基于 profile 加载测试 bean

  从 Spring 3.2 以后,Spring 开始支持使用 @ActiveProfiles 来指定测试类加载的配置包,比如您的配置文件只有一个,但是需要兼容生产环境的配置和单元测试的配置,那么您可以使用 profile 的方式来定义 beans,如下:

  清单 10. Spring-db.xml

    <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-3.2.xsd">
      
         <beans profile="test">
     <bean id="datasource"
    >
     <property name="driverClassName" value="org.hsqldb.jdbcDriver" />
         <property name="url" value="jdbc:hsqldb:hsql://localhost" />
         <property name="username" value="sa"/>
         <property name="password" value=""/>
         </bean>
    </beans>
      
    <beans profile="production">
     <bean id="datasource"
    >
         <property name="driverClassName" value="org.hsqldb.jdbcDriver" />
         <property name="url" value="jdbc:hsqldb:hsql://localhost/prod" />
         <property name="username" value="sa"/>
         <property name="password" value=""/>
         </bean>
     </beans>
     <beans profile="test,production">
     <bean id="transactionManager"
        >
         <property name="dataSource" ref="datasource"></property>
         </bean>
         <bean id="initer" init-method="init">
         </bean>
     <bean id="accountDao" depends-on="initer">
                 <property name="dataSource" ref="datasource"/>
             </bean>
      
             <bean id="accountService">
             </bean>
             <bean id="envSetter"/>
         </beans>
     </beans>

  上面的定义,我们看到:

  ● 在 XML 头中我们引用了 Spring 3.2 的 beans 定义,因为只有 Spring 3.2+ 才支持基于 profile 的定义

  ● 在 <beans> 根节点下可以嵌套 <beans> 定义,要指定 profile 属性,这个配置中,我们定义了两个 datasource,一个属于 test profile,一个输入 production profile,这样,我们能在测试程序中加载 test profile,不影响 production 数据库了

  ● 在下面定义了一些属于两个 profile 的 beans,即 <beans profile=”test,production”> 这样方便重用一些 bean 的定义,因为这些 bean 在两个 profile 中都是一样的

  清单 11. AccountServiceTest.Java

    @RunWith(SpringJUnit4ClassRunner.class) 
    @ContextConfiguration("/config/Spring-db.xml") 
    @Transactional
    @ActiveProfiles("test") 
    public class AccountServiceTest { 
    ... 
    }

  注意上面的 @ActiveProfiles,可以指定一个或者多个 profile,这样我们的测试类仅仅加载这些名字的 profile 中定义的 bean 实例。

  对 TestNG 的支持

  Spring 2.5 以后,开始支持 TestNG 了,支持的方法包括:

  ● 将您的 TestNG 测试类继承 Spring 的测试父类:AbstractTransactionalTestNGSpringContextTests 或者 AbstractTestNGSpringContextTests,这样您的 TestNG 测试类内部可以访问 applicationContext 成员变量了

  ● 不继承 Spring 父类,在测试类上使用 @TestExecutionListeners 注释标签,可以引入的监听器包括

  → DependencyInjectionTestExecutionListener:使得测试类拥有依赖注入特性

  → DirtiesContextTestExecutionListener:使得测试类拥有更新 applicationContext 能力

  → TransactionalTestExecutionListener:使得测试类拥有自动的事务管理能力

  这里我们演示一下如何使用 Spring 提供的 TestNG 父类来进行测试。

  清单 12. AccountServiceTestNGTest.Java

    package testng; 
      
    import static org.Junit.Assert.assertEquals; 
      
    import org.Springframework.beans.factory.annotation.Autowired; 
    import org.Springframework.test.context.ActiveProfiles; 
    import org.Springframework.test.context.ContextConfiguration; 
    import org.Springframework.test.context.testng. 
    AbstractTransactionalTestNGSpringContextTests; 
    import org.Springframework.transaction.annotation.Transactional; 
      
    import service.AccountService; 
    import domain.Account; 
      
    @ContextConfiguration("/config/Spring-db.xml") 
    @Transactional
    @ActiveProfiles("test") 
    public class AccountServiceTestNGTest extends
    AbstractTransactionalTestNGSpringContextTests { 
        @Autowired
        private AccountService service; 
      
        @org.testng.annotations.Test 
        public void testGetAcccountById() { 
            Account acct = Account.getAccount(1, "user01", 18, "M"); 
            service.insertIfNotExist(acct); 
            Account acct2 = service.getAccountById(1); 
            assertEquals(acct,acct2); 
        } 
    }