开发者社区 问答 正文

零XML配置测试Spring&Hibernate应用 配置错误

我很热衷于在编译器和IDE的支持下通过移除XML文件来提升Spring3的开发效率,而这并不会改变Spring给你提供的强大的功能。

没有XML配置文件的Hibernate的单元测试是可行的,但是竟然花了我好一会才找到所有的东西,所以就在这里写下来。

我将在一个使用@Configuration注解的类中初始化所有的bean。

@Configuration @EnableTransactionManagement public class TestRepositoryConfig {
@Bean 
public DataSource dataSource() {
	return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2)
			.setName("Nuts").build();
}

@Bean 
public LocalSessionFactoryBean sessionFactoryBean() {
	LocalSessionFactoryBean result = new LocalSessionFactoryBean();
	result.setDataSource(dataSource());
	result.setPackagesToScan(new String[] { "pl.squirrel.testnoxml.entity" });

	Properties properties = new Properties();
	properties.setProperty("hibernate.hbm2ddl.auto", "create-drop");
	result.setHibernateProperties(properties);
	return result;
}

@Bean 
public SessionFactory sessionFactory() {
	return sessionFactoryBean().getObject();
}

@Bean 
public HibernateTransactionManager transactionManager() {
	HibernateTransactionManager man = new HibernateTransactionManager();
	man.setSessionFactory(sessionFactory());
	return man;
}

@Bean 
public OrderRepository orderRepo() {
	return new OrderRepository();
}

}

测试类是这样的:

@RunWith(SpringJUnit4ClassRunner.class) @TransactionConfiguration(defaultRollback = true) @ContextConfiguration(classes = { TestRepositoryConfig.class }) @Transactional public class OrderRepositoryTest {
@Autowired
private OrderRepository repo;

@Autowired
private SessionFactory sessionFactory;

@Test 
public void testPersistOrderWithItems() {
	Session s = sessionFactory.getCurrentSession();

	Product chestnut = new Product("Chestnut", "2.50");
	s.save(chestnut);
	Product hazelnut = new Product("Hazelnut", "5.59");
	s.save(hazelnut);

	Order order = new Order();
	order.addLine(chestnut, 20);
	order.addLine(hazelnut, 150);

	repo.saveOrder(order);
	s.flush();

	Order persistent = (Order) s.createCriteria(Order.class).uniqueResult();
	Assert.assertNotSame(0, persistent.getId());
	Assert.assertEquals(new OrderLine(chestnut, 20), persistent
			.getOrderLines().get(0));
	Assert.assertEquals(new OrderLine(hazelnut, 150), persistent
			.getOrderLines().get(1));
}

}

这里有几个需要注意的细节:

  • 我在测试上使用了@Transactional注解,然后我将可以直接访问Session。
  • 如果测试没有使用@Transactional注解,事务将总是忽略掉@TransactionConfiguration提交。
  • 如果测试使用了@Transactional注解,@TransactionConfiguration将被视为默认配置。即使他被忽略了,在test执行最后的时候事务也将回滚,如果你想让他提交,就是用@TransactionConfiguration(defaultRollback=false).
  • 对于不同的生产环境而言,测试的@Configuration可能都不同,我这里使用的是嵌入式的H2数据库,对于真实的应用我将在测试数据库上使用相同的引擎。
大家也都看到了,仅仅就两个java类,没有XML。你可以通过这里查看我在Github上托管的

展开
收起
huc_逆天 2020-05-28 09:19:01 497 分享 版权
阿里云 AI 助理回答

您采用的无XML配置方式利用Spring 3的Java配置功能来提升开发效率,是一个很好的实践。这种方式不仅让配置更加类型安全,也使得代码结构更为清晰,便于维护和版本控制。通过使用@Configuration, @Bean, @EnableTransactionManagement等注解,您直接在Java类中定义了bean的创建逻辑和依赖关系,以及事务管理设置。

关键点回顾:

  1. @Configuration:标记该类为配置类,相当于一个或多个Spring XML配置文件。

  2. @Bean:声明在方法上,表示该方法将返回一个对象,该对象将被注册为Spring应用上下文中的bean。

  3. @EnableTransactionManagement:启用基于注解的事务管理,通常与AOP(面向切面编程)一起工作,以实现事务的自动管理。

  4. @Autowired:自动装配bean,Spring会根据类型从应用上下文中找到匹配的bean并注入。

  5. @RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration:这两个注解用于Spring集成测试,确保测试运行时能加载指定的配置类,并且能够使用Spring的依赖注入功能。

  6. @Transactional@TransactionConfiguration:用于控制测试方法的事务行为,如默认回滚、事务传播行为等,简化了数据库操作的前后处理,保持测试环境的干净。

  7. 嵌入式数据库(H2):在单元测试中使用嵌入式数据库可以快速搭建测试环境,无需外部数据库支持,加快测试速度,同时保证测试的隔离性。

实践建议:

  • 多环境配置:对于不同的生产环境,您可以考虑使用Spring Profile来区分不同环境的配置,比如开发、测试、生产环境的数据库连接信息等。

  • 持续集成/持续部署(CI/CD):结合Git托管的代码仓库,自动化构建和测试流程,确保每次提交都能经过充分的测试,提高软件质量。

  • 资源管理:虽然您的示例中直接在配置类中创建了嵌入式数据库,但在实际项目中,可能需要更细致地管理资源生命周期,特别是对于非嵌入式数据库的连接池配置等。

  • 文档和注释:随着配置复杂度的增加,良好的文档和代码注释对于团队协作至关重要,确保其他开发者能快速理解配置意图。

您提到的GitHub托管链接未提供,但如果您有公开的代码库,分享出来可以让更多人学习和交流,也是对开源社区的一大贡献。

有帮助
无帮助
AI 助理回答生成答案可能存在不准确,仅供参考
0 条回答
写回答
取消 提交回答