5

我有一个 JPA/Hibernate/Spring/Tomcat Web 应用程序,出于性能原因启用了二级数据缓存。缓存做得很好!

我还有一个 Cucumber 测试套件,它直接将一些测试数据添加到应用程序的数据库中,然后执行一些 Selenium 步骤。当然它会失败,因为应用程序由于二级缓存而看不到更新。

我知道我可以为禁用缓存的测试进行特殊构建(通过传递一些用于 Maven 过滤或类似的布尔属性)但是有很多 @Cache 注释实体,因此禁用缓存会使应用程序失败,并出现异常“二级缓存不是启用”。

另一种方法可能是使用 ehcache 远程处理来清除缓存或将其配置为零对象生命周期或类似的。

我也可以仅使用应用程序 UI 创建我的测试数据,但这会给测试用例增加不必要的复杂性,因此我更喜欢在测试运行之前将它们写入数据库。

有人可以分享他们启用二级数据缓存的集成测试应用程序的方法吗?

4

4 回答 4

1

如果您需要使用单元测试来测试二级缓存,您必须确保在每次调用 dao 方法时关闭会话并打开它。否则,您将使用仅存在于一个/当前休眠会话范围内的一级缓存。

于 2012-06-25T15:28:57.577 回答
0

虽然让验收测试独立于数据库是可取的,但它需要太多的重写,所以我目前决定只创建 org.hibernate.cache.Cache 和 org.hibernate.cache.CacheProvider 接口的非常简单的实现,它们什么都不做,并且总是空缓存。

测试构建用这个新的缓存替换了真正的缓存,这使得休眠注释和 BDD 步骤都很开心。

于 2012-04-28T03:29:14.603 回答
0

我需要为国家、地区等少数 bean实现只读缓存。

为了检查它们是否真的被缓存了,我使用 spring编写了一个集成测试。测试不太合适,它只是对我想要得到的东西的验证。您可以将其用作提示并实现自己的提示。

您可以在此处阅读有关如何使用 spring 编写集成测试的文章。

@Configurable(autowire = Autowire.BY_NAME)
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext.xml" })
public class HibernateCachingTestIntg {

    @Autowired
    private ConfigurationDAO configurationDAO;

    @Autowired
    private CountryDAO countryDAO;

    @Test
    public void testGetCountries() {
        for (int i = 0; i < 5; i++) {
            StopWatch sw = new StopWatch("C");
            sw.start();
            countryDAO.listCountries();
            sw.stop();
            System.out.println(sw);
        }

    }

    @Test
    public void testGetRegionList() {

        for (int i = 0; i < 5; i++) {
            StopWatch sw = new StopWatch("R");
            sw.start();
            configurationDAO.getRegionList();
            sw.stop();
            System.out.println(sw);
        }

    }
}

这是输出: -

StopWatch 'C': running time (millis) = 217; [] took 217 = 100%
StopWatch 'C': running time (millis) = 15; [] took 15 = 100%
StopWatch 'C': running time (millis) = 16; [] took 16 = 100%
StopWatch 'C': running time (millis) = 15; [] took 15 = 100%
StopWatch 'C': running time (millis) = 16; [] took 16 = 100%

StopWatch 'R': running time (millis) = 201; [] took 201 = 100%
StopWatch 'R': running time (millis) = 15; [] took 15 = 100%
StopWatch 'R': running time (millis) = 0; [] took 0 = 0%
StopWatch 'R': running time (millis) = 16; [] took 16 = 100%
StopWatch 'R': running time (millis) = 15; [] took 15 = 100%

正如您在此处看到的,查询第一次执行需要更多时间,而后执行时间更少。如果您打开查询记录器,您可以看到SQL只是第一次被触发。

于 2012-04-27T04:15:47.923 回答
0

由于您在谈论通过 Selenium 进行的功能测试,因此您应该将您的应用程序视为一个黑匣子,并在 Selenium 实际上是一个用户时对其进行测试。因此,您需要通过 Web 界面传递数据,然后测试应用程序如何处理它并在之后显示它。

替代此类应用程序范围的功能测试将是行为驱动开发,其中包含针对不同组件的测试。这里的组件是从你的控制器开始的一些流程,以 DAO 结尾(通常 DAO 在这样的测试中被模拟,这使得它们通过非常快,但不测试使用数据库)。在这种情况下,您有一组完整的环境测试和大量的 BDD 测试。

于 2012-04-27T07:18:10.363 回答