当前位置: 首页 > 知识库问答 >
问题:

缓存已关闭,导致运行测试套件时出现异常

段干浩荡
2023-03-14

我遇到了一个类似于这个问题中描述的问题。

我有一个在开发环境中运行良好的测试套件。其中一个测试在比特桶管道中执行时失败,但以下例外:

org.springframework.dao.InvalidDataAccessApiUsageException: Cache[model.Role] is closed; nested exception is java.lang.IllegalStateException: Cache[model.Role] is closed
    at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:364)
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:225)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:527)
    at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
    at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)
   ....

我想尝试公认的解决方案,但我不知道如何将其应用到我的项目中。第二种解决方案依赖于ehcache。xml文件。我没有这个文件,一切都是在JavaConfig中配置的。我如何在JavaConfig中采用针对EhCache-JCache(JSR-107)的拟议解决方案?

我的缓存配置:

@Configuration
@EnableCaching
public class CacheConfig {

    private final javax.cache.configuration.Configuration<Object, Object> jcacheConfiguration =
            Eh107Configuration.fromEhcacheCacheConfiguration(CacheConfigurationBuilder
                    .newCacheConfigurationBuilder(Object.class, Object.class,
                            ResourcePoolsBuilder.newResourcePoolsBuilder()
                                    .heap(100, EntryUnit.ENTRIES))
                    .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofSeconds(60)))
                    .build());

    @Bean
    public JCacheManagerCustomizer cacheManagerCustomizer() {
        return cm -> {
            createIfNotExists(cm, "model.Role");
            createIfNotExists(cm, "model.User.roles");
            // ...
        };
    }

    private void createIfNotExists(CacheManager cacheManager, String cacheName) {
        if (cacheManager.getCache(cacheName) == null) {
            cacheManager.createCache(cacheName, jcacheConfiguration);
        }
    }
}

Gradle依赖项:

implementation group: 'org.springframework.boot', name: 'spring-boot-starter-cache'
implementation group: 'javax.cache', name: 'cache-api'
implementation group: 'org.ehcache', name: 'ehcache'
implementation group: 'org.hibernate', name: 'hibernate-jcache'

失败的测试:

@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class SecondLevelCacheTest {
    @Autowired
    private RoleRepository roleRepository;
    private CacheManager manager;

    @Before
    public void initCacheManager() {
        CachingProvider provider = Caching.getCachingProvider();
        manager = provider.getCacheManager();

        final String cacheRegion = "model.Role";
        manager.getCache(cacheRegion).clear();
    }

    @Test
    public final void givenEntityIsLoaded_thenItIsCached() {
        final String cacheRegion = "model.Role";

        boolean hasNext = manager.getCache(cacheRegion).iterator().hasNext();
        final Role role = roleRepository.findByName("USER");
        boolean hasNext2 = manager.getCache(cacheRegion).iterator().hasNext();
        final Role role2 = roleRepository.findByName("USER");

        Assert.assertFalse(hasNext);
        Assert.assertTrue(hasNext2);
    }
}

投票最多的解决方案是“在测试上下文中将共享属性设置为false”关于我的配置,我如何做到这一点?

共有3个答案

柏阳炎
2023-03-14

用AutoConfigureCache注释失败的测试类。默认情况下,此注释将安装NoOpCacheManager,即适用于禁用缓存的基本无操作CacheManager实现,通常用于在没有实际备份存储的情况下备份缓存声明。它只会将任何项目接收到缓存中,而不是实际存储它们。

@AutoConfigureCache上的Spring文档

@NoOpCacheManager上的Spring文档

端木野
2023-03-14

您正在谈论的建议解决方案基于Ehcache 2。您正在使用Ehcache 3(对您有好处),因此它无效。

Spring将负责关闭CacheManager,因此通常情况下,您不需要处理任何事情。此外,您不需要通过CachingProvider访问它。您可以使用javax。隐藏物CacheManager,这样您一定会找到正确的。

但是,您正在使用Hibernate。您应该确保Spring和Hibernate使用相同的CacheManager。配置它的方式取决于Spring和Hibernate版本。

我们能有完整的堆栈跟踪吗?现在感觉好像有什么东西在关闭CacheManager而没有从CachingProvider中注销它。这是不可能的,除非您在关闭org.ehcache.CacheManager而没有关闭包装它的javax.cache.CacheManager。关闭稍后将导致注销。

甄伟兆
2023-03-14

一种选择是提供一个自定义的CachingProvider,它不共享CacheManager。可以在这里找到一个示例解决方案

 类似资料:
  • 我正在尝试为基于Hibernate 5.3和Spring Boot 2.1.3并使用Hibernate二级缓存的应用程序编写测试。 当我执行一批测试时,这些测试正在设置Spring上下文并试图更新一些JPA实体,在某个时候会出现这样的异常: 我为Hibernate二级缓存提供了以下配置: 并使用Hibernate JCache作为依赖项。 据我所知,对Spring Test创建的所有上下文重用同一

  • 当我试图再次运行同样的测试时: 如何禁用缓存,以便gradlew运行整个测试? 谢谢

  • 创建一个应用程序,使用和从API调用数据。 java和XML文件中没有错误消息。但当我运行应用程序时。很接近。 它的日志上有这条信息。 08-07 16:45:13.735 18311-18311/? D/Android运行时:关闭VM 08-07 16:45:13.739 18311-18311/?E/Android运行时:致命异常:主进程:eldarcreative.myapplication

  • 我使用以下spock依赖项 我写了这个测试 测试成功 现在我想使用Spring在规范中注入用注释,并在运行应用程序时成功注入。测试和组件都放在同一个maven模块中。 我在这里阅读了关于:如何将Spring bean注入spock测试 因此我添加了这个依赖版本 在添加了运行s的依赖后 然后我尝试使用适当的注释 结果仍然是上述例外。 groovy测试在下,这是一个可以在第一次成功运行测试时看到的工作

  • 在Eclipse中运行JUnit测试时,我会收到以下错误: 虽然我使用的是maven,但我尝试在类路径中添加库,并且JUnit库位于POM依赖项中。 我已经尝试过清理该项目,并使用Eclipse的JUnit插件创建了一个新的JUnit测试用例,但仍然得到相同的错误。