`
dengyin2000
  • 浏览: 1225598 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

使用Spring AbstractTransactionalDataSourceSpringContextTests测试

阅读更多
在使用AbstractTransactionalDataSourceSpringContextTests这个作为测试hibernate的Service时,遇到这样的一个问题。 就是一定要在代码中显示的调用session.flush()。 更改操作才能立即看到。。

比如

	public void testDeleteBillingEntity(){
		getBillingEntityService().deleteBillingEntity(1);
		assertEquals("BillingEntity(1) should be not existed", getJdbcTemplate().queryForInt("SELECT COUNT(*) FROM BILLING_ENTITY WHERE ID=1"), 0);
	}


如果我不在getBillingEntityService().deleteBillingEntity(1) 方法里面调用sesson.flush()的话。 这个测试是失败的。但是在真是环境中的话不调用session.flush()是能行的。Hibernate 默认的是autoFlush 大家应该也遇到相同的问题吧。 是如何解决的?

谢谢
分享到:
评论
29 楼 dengyin2000 2007-05-15  
zhour560 写道
我也遇到Spring AbstractTransactionalDataSourceSpringContextTests测试不可以回滚的问题。数据库是MYSQL。在测试里面新增记录的时候,竟然加数据库里面去了。而且更新和删除都可以回滚的!
public abstract class SpringTestCaseBase extends AbstractTransactionalDataSourceSpringContextTests {
protected SimpleDateFormat sdf;

public SpringTestCaseBase() {
// query the protected variables to implement denpendency injection automatically,
// so we don't need to write settor and gettor methods anymore.
this.setPopulateProtectedVariables(true);

sdf = new SimpleDateFormat("yyyy-MM-dd");
sdf.setTimeZone(TimeZone.getDefault());
}

protected String[] getConfigLocations() {
return new String[] { "file:web/WEB-INF/applicationContext*.xml",
          "file:web/WEB-INF/test-ApplicationContext*.xml"};
    }

protected void flushSession(){
SessionFactory sessionFactory = (SessionFactory)applicationContext.getBean("sessionFactory");  
        sessionFactory.getCurrentSession().flush();
    }
}
这是我测试基类。


看看你mysql数据库是什么类型的。 ISM类型的应该不能回滚,因为不支持事务。 换成innodb
28 楼 zhour560 2007-05-15  
我也遇到Spring AbstractTransactionalDataSourceSpringContextTests测试不可以回滚的问题。数据库是MYSQL。在测试里面新增记录的时候,竟然加数据库里面去了。而且更新和删除都可以回滚的!
public abstract class SpringTestCaseBase extends AbstractTransactionalDataSourceSpringContextTests {
protected SimpleDateFormat sdf;

public SpringTestCaseBase() {
// query the protected variables to implement denpendency injection automatically,
// so we don't need to write settor and gettor methods anymore.
this.setPopulateProtectedVariables(true);

sdf = new SimpleDateFormat("yyyy-MM-dd");
sdf.setTimeZone(TimeZone.getDefault());
}

protected String[] getConfigLocations() {
return new String[] { "file:web/WEB-INF/applicationContext*.xml",
          "file:web/WEB-INF/test-ApplicationContext*.xml"};
    }

protected void flushSession(){
SessionFactory sessionFactory = (SessionFactory)applicationContext.getBean("sessionFactory");  
        sessionFactory.getCurrentSession().flush();
    }
}
这是我测试基类。
27 楼 dengyin2000 2007-05-11  
用session.get试试
26 楼 晨星★~雨泪 2007-05-11  
我总觉得既然已删除 那么查出的结果应为NULL 才对,为什么要报错?
如果我 用 Hibernate findByid 去查一个数据表里没有的记录 那不是老抛异常.
25 楼 spiritfrog 2007-05-10  
晨星★~雨泪 写道
我用 Hibernate delete 后 用Spring JdbcTemplate 查被删的记录还是存在,可用 Hibernate findByid 就会报 该记录已删 的错误.郁闷

hibernate delete只是在缓存中将某个持久对象给标记成删除的,但没有flunsh就实际没有执行删除操作,而JdbcTemplate不在session控制之下,因此还能从数据库找到标记为删除的记录。当然,被标记为删除的记录,再次通过hibernate来查找就会抛出异常,说已经被删除了。
24 楼 spiritfrog 2007-05-10  
这里是需要调用session的flunsh的,因为getJdbcTemplate().queryForInt方法不会flunsh缓存。
23 楼 晨星★~雨泪 2007-05-10  
我用 Hibernate delete 后 用Spring JdbcTemplate 查被删的记录还是存在,可用 Hibernate findByid 就会报 该记录已删 的错误.郁闷
22 楼 温柔一刀 2007-04-14  
dada 写道
我不认为测试一定要直接操作数据库,尤其是用hibernate的时候。


如果用了hibernate

测试的时候用hsqldb就可以了
21 楼 dada 2007-04-11  
dengyin2000 写道
刚刚看了下,确实是拿的session cache中的对象, 根本没有发送select 语句

这段代码的本意就是判断session中的对象是否被删除了。
前头漏了段
public void testDelete() {
    Sample sample = dao.get(new Long(1));
    dao.delete(sample);
    Object obj = dao.get(new Long(1));
    AssertNull(obj);
}

我不认为测试一定要直接操作数据库,尤其是用hibernate的时候。
20 楼 dengyin2000 2007-04-11  
刚刚看了下,确实是拿的session cache中的对象, 根本没有发送select 语句
19 楼 dengyin2000 2007-04-11  
dada 写道
dengyin2000 写道
总结下, 应该commit transaction才会触发session 的flush的吧。

刚才看了下AbstractTransactionalDataSourceSpringContextTests这个类。他是在onSetup的时候开始transaction 然后在onTeardown时commit transaction。 所以如果不显示调用session.flush的话,table里面是不会有变化的。所以我的设想应该是正确的,flushCurrentSession()方法里面拿的是同一个session。


想要看到数据变化的话 在你的测试方法里面调用下flushCurrentSession()方法就行。。

    protected SessionFactory getSessionFactory(){
    	return (SessionFactory) getApplicationContext().getBean("sessionFactory");
    }
    
    protected void flushCurrentSession(){
    	Session session = SessionFactoryUtils.getSession(getSessionFactory(), false);
    	if (session !=null){
    		session.flush();
    	}
    }


我觉得改变测试方法比较好:
public void testDelete() {
    service.delete(new Long(1));
    Object obj = service.get(new Long(1));
    assertNull(obj);
}


刚刚又想到了你这样会不会有问题。看下面的代码,我把delete变成了save

public void testSave() {
    service.save(new Long(1));
    Object obj = service.get(new Long(1));
    assertNull(obj);
}


因为在testSave中是在一个session中, 所以service.get的话可能根本不会读数据库里面的值, 而是拿的session cache中的?
18 楼 dengyin2000 2007-04-11  
Godlikeme 写道
Godlikeme 写道
每次调用,应该是取的不同的session,这样是不对的,参见HibernateTemaplate.executeWithSession

这个问题我看错了,原来问题是jdbctemplate.execute(),不是不同session的问题。
只能显示调用sessionFlush了,hibernateTemplate和jdbcTemplate一块用,这样不一致性的问题就会一直存在。


是的  我没有发现,hibernateTemplate有executeWithSession这个方法。
正规的话 当然是应该用jdbc来测试的。 
17 楼 Godlikeme 2007-04-11  
Godlikeme 写道
每次调用,应该是取的不同的session,这样是不对的,参见HibernateTemaplate.executeWithSession

这个问题我看错了,原来问题是jdbctemplate.execute(),不是不同session的问题。
只能显示调用sessionFlush了,hibernateTemplate和jdbcTemplate一块用,这样不一致性的问题就会一直存在。
16 楼 Godlikeme 2007-04-11  
tsingn 写道
Godlikeme 写道
每次调用,应该是取的不同的session,这样是不对的,参见HibernateTemaplate.executeWithSession
同意!
但是不知道为什么用不同的session flush一下也会起作用?

flush后session是与数据库同步的,因为测试不是多线程,session之间就不会出现不一致的情况。
15 楼 dengyin2000 2007-04-11  
dada 写道
dengyin2000 写道
总结下, 应该commit transaction才会触发session 的flush的吧。

刚才看了下AbstractTransactionalDataSourceSpringContextTests这个类。他是在onSetup的时候开始transaction 然后在onTeardown时commit transaction。 所以如果不显示调用session.flush的话,table里面是不会有变化的。所以我的设想应该是正确的,flushCurrentSession()方法里面拿的是同一个session。


想要看到数据变化的话 在你的测试方法里面调用下flushCurrentSession()方法就行。。

    protected SessionFactory getSessionFactory(){
    	return (SessionFactory) getApplicationContext().getBean("sessionFactory");
    }
    
    protected void flushCurrentSession(){
    	Session session = SessionFactoryUtils.getSession(getSessionFactory(), false);
    	if (session !=null){
    		session.flush();
    	}
    }


我觉得改变测试方法比较好:
public void testDelete() {
    service.delete(new Long(1));
    Object obj = service.get(new Long(1));
    assertNull(obj);
}


我有遇到你这种情况, 一个同事使用jdbc去验证的时候 会有问题, 但是我用service去拿的话 就能通过。 最后发现我这里发送了update语句,而用jdbc去验证的话并没有flush。 我不觉得你上面的方式好。 因为我这种方式对于使用jdbc或者其他方式去验证都是有效的, 而且如果我没有get find方法呢? 我还要为测试去加多这样的方法?
14 楼 dada 2007-04-11  
dengyin2000 写道
总结下, 应该commit transaction才会触发session 的flush的吧。

刚才看了下AbstractTransactionalDataSourceSpringContextTests这个类。他是在onSetup的时候开始transaction 然后在onTeardown时commit transaction。 所以如果不显示调用session.flush的话,table里面是不会有变化的。所以我的设想应该是正确的,flushCurrentSession()方法里面拿的是同一个session。


想要看到数据变化的话 在你的测试方法里面调用下flushCurrentSession()方法就行。。

    protected SessionFactory getSessionFactory(){
    	return (SessionFactory) getApplicationContext().getBean("sessionFactory");
    }
    
    protected void flushCurrentSession(){
    	Session session = SessionFactoryUtils.getSession(getSessionFactory(), false);
    	if (session !=null){
    		session.flush();
    	}
    }


我觉得改变测试方法比较好:
public void testDelete() {
    service.delete(new Long(1));
    Object obj = service.get(new Long(1));
    assertNull(obj);
}
13 楼 tsingn 2007-04-11  
AbstractTransactionalDataSourceSpringContextTests里面的tearDown有两个方法:onTearDownInTransaction和onTearDownAfterTransaction
所以你可以试着把flush的操作放在onTearDownInTransaction里面看看,这样你不用每次都要在测试方法里面调用了!
完了把测试结果贴一下,呵呵。
12 楼 dengyin2000 2007-04-11  
总结下, 应该commit transaction才会触发session 的flush的吧。

刚才看了下AbstractTransactionalDataSourceSpringContextTests这个类。他是在onSetup的时候开始transaction 然后在onTeardown时commit transaction。 所以如果不显示调用session.flush的话,table里面是不会有变化的。所以我的设想应该是正确的,flushCurrentSession()方法里面拿的是同一个session。


想要看到数据变化的话 在你的测试方法里面调用下flushCurrentSession()方法就行。。

    protected SessionFactory getSessionFactory(){
    	return (SessionFactory) getApplicationContext().getBean("sessionFactory");
    }
    
    protected void flushCurrentSession(){
    	Session session = SessionFactoryUtils.getSession(getSessionFactory(), false);
    	if (session !=null){
    		session.flush();
    	}
    }
11 楼 tsingn 2007-04-11  
dada 写道
一个测试方法一个transaction,assertEquals这里session还没有关闭,所以你测试不会通过。

这样说就能够解释了,我一直以为session在dao.delete()方法结束后就关闭了。哈哈
10 楼 dada 2007-04-11  
一个测试方法一个transaction,assertEquals这里session还没有关闭,所以你测试不会通过。

相关推荐

    spring单元测试包

    spring单元测试包spring单元测试包spring单元测试包spring单元测试包spring单元测试包

    spring websocket 测试项目

    这个"spring websocket 测试项目"是为了帮助开发者理解和实践如何在实际应用中集成和使用WebSocket。 首先,我们要了解Spring WebSocket的基础架构。它基于STOMP(Simple Text Oriented Message Protocol)协议,这...

    使用 Spring 2.5 TestContext 测试框架

    在本篇文章中,我们将深入探讨Spring 2.5 TestContext测试框架的核心特性和使用方法。 首先,Spring TestContext框架的核心是`@ContextConfiguration`注解,它用于指定测试类中应用上下文的配置。你可以通过此注解...

    spring测试示例代码

    本示例代码聚焦于使用JUnit进行Spring测试,这是一项核心的Java测试框架,广泛用于编写可重复的、独立的单元测试。 首先,让我们深入理解Spring测试的基本概念。Spring测试支持主要由`spring-test`模块提供,它包含...

    spring整合单元测试Junit开发包

    9. **AssertJ和Hamcrest**: Spring Test通常与这些强大的断言库结合使用,提供更清晰、表达力更强的断言,帮助编写更具可读性的测试代码。 10. **Mock Beans**: 可以使用`@MockBean`和`@SpyBean`注解在测试上下文中...

    spring-demo15-测试.zip

    在Spring中,我们可以使用`@RunWith(SpringRunner.class)`注解来运行测试类,同时用`@ContextConfiguration`或`@SpringBootTest`注解加载相应的上下文配置。这样,我们可以利用`@Autowired`注解注入依赖,并使用`@...

    Spring Cloud Contract 测试学习

    4. **使用Spring Cloud Contract步骤** - **添加依赖**:在服务提供者和消费者项目中引入Spring Cloud Contract相关依赖。 - **编写契约**:在`src/main/resources/contracts`目录下创建契约文件。 - **配置**:...

    最小配置Spring-测试

    最小配置Spring-测试

    spring security测试

    5. **测试访问控制表达式**:Spring Security允许我们在配置中使用SpEL(Spring Expression Language)表达式来定义访问控制规则。在单元测试中,可以创建特定的访问控制表达式测试用例,确保它们按预期评估。 6. *...

    07. Spring Boot单元测试

    同时,Spring Boot提供了`@SpringBootTest`注解,用于启动一个完整的Spring应用上下文,这样可以在测试中使用到Spring的所有功能。 三、Mockito与Spring Boot测试 Mockito是一个流行的Java单元测试框架,它允许我们...

    Spring 测试jar

    在进行Spring测试时,开发者通常会使用`@RunWith(SpringRunner.class)`来启用Spring的测试支持,然后通过`@SpringBootTest`或更具体的测试注解来指定测试范围。`@Autowired`注解可以帮助注入需要的bean,而`@Mock...

    Spring3单元测试和集成测试

    在Spring3中,我们可以使用JUnit作为主要的测试框架,结合`@RunWith(SpringJUnit4ClassRunner.class)`注解来启动Spring上下文,使得测试类能够访问到Spring的bean。例如: ```java import org.junit.Test; import ...

    spring集成测试工具的详细讲解

    本文将详细讲解Spring集成测试工具的使用和重要性。 首先,集成测试是在所有组件被组装到一起后进行的测试,目的是发现模块间的接口问题。Spring提供了一些工具和库,如Spring Test、Spring Boot Test和Mockito,来...

    Spring测试框架.rar

    这个压缩包“Spring测试框架.rar”包含了与使用Spring 2.5 TestContext测试框架相关的资源,特别是文档“使用 Spring 2.5 TestContext 测试框架.htm”和其相关的文件夹“使用 Spring 2.5 TestContext 测试框架_files...

    springcloud开发测试工具集

    本文以JD-GUI为例,介绍了如何使用该工具来辅助Spring Cloud的开发和测试。通过有效的工具支持,开发者可以更专注于业务逻辑的实现,减少在基础架构层面上的困扰,从而提高整体项目的开发质量和速度。在实际工作中,...

    Spring、Spring Boot和TestNG测试指南1

    本指南旨在帮助开发者更好地理解和使用Spring、Spring Boot框架中的TestNG测试工具。TestNG是一个功能强大的测试框架,它提供了比JUnit更多的功能,如并行测试、测试配置、支持多种测试类型等。 **认识TestNG** ...

    详解spring cloud如何使用spring-test进行单元测试

    本文将介绍如何使用 Spring Test 框架对 Spring Cloud 应用程序进行单元测试。 什么是单元测试 单元测试是软件测试的一种,它通过编写测试代码来验证单个软件单元(例如函数、方法、类等)的正确性。单元测试的...

    spring mvc的简单单元测试

    3. **Spring Test**:Spring 提供了自己的测试模块,包含`@RunWith(SpringRunner.class)`注解,它可以将JUnit测试与Spring环境结合,自动加载ApplicationContext,使得我们可以使用依赖注入来测试bean。 4. **@...

    Spring整合Junit框架进行单元测试Demo

    为了更好地模拟实际运行环境,我们可能需要在Spring配置文件中定义一些mock bean,或者使用`@MockBean`和`@SpyBean`等Spring Boot测试注解来创建mock对象。这样,我们可以在测试中控制这些mock对象的行为,以便更...

Global site tag (gtag.js) - Google Analytics