question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Integration tests with Spring Boot @MockBean - already cache named error

See original GitHub issue
  • Please follow the issue template below for bug reports and feature requests.
  • Tickets opened without any of these informations will be closed without any explanation.
Overview of the issue

If you use org.springframework.boot.test.mock.mockito.MockBean annotation in an integration test, Spring Boot failed to load application due to an issue on duplicate cache key com.mycompany.myapp.domain.User

Stack trace: (full stack here stack.txt)

testGetExistingUser(com.mycompany.myapp.web.rest.UserResourceIntTest) Time elapsed: 0 sec <<< ERROR! java.lang.IllegalStateException: Failed to load ApplicationContext at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124) at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) … Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘jCacheCacheManager’ defined in class path resource [org/springframework/boot/autoconfigure/cache/JCacheCacheConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.spri ngframework.beans.BeanInstantiationException: Failed to instantiate [javax.cache.CacheManager]: Factory method ‘jCacheCacheManager’ threw exception; nested exception is javax.cache.CacheException: A Cache named [com.mycompany.myapp.domain.User] already exists

Motivation for or Use Case

Bug preventing the use of service mocks

Reproduce the error

1/ Generate a new JHipster 4.0.7 application with EHCache. 2/ Add in any integration test a @MockBean for any service.

Example: in UserServiceIntTest add the following declaration:

@MockBean private MailService mailService;

3/ Run ./mvnw clean test

Related issues

N/A

Suggest a Fix

I supect the recent change to the java config EhCache and the CacheConfiguration.java. Maybe the cache pool is not full clean between two consecutive tests.

I also notice:

  • On the first test execution it’s ok
  • If the test is running only it’s also ok (with IDE or mvn test -Dtest=… )

The issue was not occur on the previous Jhipster v4.0.6

JHipster Version(s)

JHipster v4.0.7

JHipster configuration

yo jhipster:info Welcome to the JHipster Information Sub-Generator

JHipster Version(s)
elastic@0.0.0 D:\workspaces\jhipster\elastic
+-- UNMET PEER DEPENDENCY @angular/compiler@2.4.7
+-- UNMET PEER DEPENDENCY @angular/core@2.4.7
`-- generator-jhipster@4.0.7

JHipster configuration, a .yo-rc.json file generated in the root folder
{
  "generator-jhipster": {
    "jhipsterVersion": "4.0.7",
    "baseName": "elastic",
    "packageName": "com.mycompany.myapp",
    "packageFolder": "com/mycompany/myapp",
    "serverPort": "8080",
    "authenticationType": "session",
    "hibernateCache": "ehcache",
    "clusteredHttpSession": false,
    "websocket": false,
    "databaseType": "sql",
    "devDatabaseType": "h2Disk",
    "prodDatabaseType": "postgresql",
    "searchEngine": false,
    "messageBroker": false,
    "serviceDiscoveryType": false,
    "buildTool": "maven",
    "enableSocialSignIn": false,
    "rememberMeKey": "069a6edee67a2da006eb9b7c2ed32aef688b40c1",
    "clientFramework": "angular2",
    "useSass": true,
    "clientPackageManager": "yarn",
    "applicationType": "monolith",
    "testFrameworks": [],
    "jhiPrefix": "jhi",
    "enableTranslation": false
  }
}
Entity configuration(s) entityName.json files generated in the .jhipster directory

ls: no such file or directory: .jhipster/*.json

Browsers and Operating System

java version “1.8.0_112” Java™ SE Runtime Environment (build 1.8.0_112-b15) Java HotSpot™ 64-Bit Server VM (build 25.112-b15, mixed mode)

git version 2.11.0.windows.1

node: v6.9.5

npm: 3.10.10

yeoman: 1.8.5

yarn: 0.18.1

Browsers and Operating System

OS x64 : Nom du système d’exploitation Microsoft Windows 10 Famille Version 10.0.14393 Numéro 14393

  • Checking this box is mandatory (this is just to show you read everything)

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Reactions:1
  • Comments:5 (5 by maintainers)

github_iconTop GitHub Comments

5reactions
henri-tremblaycommented, Mar 4, 2017

This is a funny issue. The problem comes from JCache mixed with the programmatic configuration.

When @MockBean is used, it forces Spring to create multiple application context. Because a context with a mock is obviously not the same as a context without the mock.

When the first context is created, it registers a CacheManager in the JCache CachingProvider. The JCacheManagerCustomizer is then called to configure this new CacheManager.

When the second context is created, it retrieves the same CacheManager since the same URI is used. And calls the JCacheManagerCustomizer again. Fail. It was working before because the ehcache.xml was loaded once and there was no customizer.

There is no way to clean the CachingProvider. @PreDestroy is called at the end of all tests. No solution there.

Using spring.cache.type=none works perfectly since it deactivate the cache. No CachingProvider issue anymore. So if we are sure we don’t want any caching during test, that’s probably a good solution. It doesn’t test the cache during testing but does remove a lot of entropy in the unit tests.

I was close to consider it a bug in spring-boot. They should not customize the CacheManager twice. But JCache gives no way to know a CacheManager was already existing.

The other solution is to check if the cache already exist.

@Bean
public JCacheManagerCustomizer cacheManagerCustomizer() {
    return cm -> {
        createIfNotExists(cm, com.mycompany.myapp.domain.User.class.getName());
        createIfNotExists(cm, com.mycompany.myapp.domain.Authority.class.getName());
        createIfNotExists(cm, com.mycompany.myapp.domain.User.class.getName() + ".authorities");
        createIfNotExists(cm, com.mycompany.myapp.domain.PersistentToken.class.getName());
        createIfNotExists(cm, com.mycompany.myapp.domain.User.class.getName() + ".persistentTokens");
        // jhipster-needle-ehcache-add-entry
    };
}

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

The bad side of it is that it is production code hacked to work with tests. But it is not a none sense either.

Please tell me what you prefer and I will do a pull-request accordingly.

0reactions
jduboiscommented, Mar 4, 2017

I would just do spring.cache.type=none as:

  • it’s much simpler
  • it would work as in the previous versions

I prefer to have the cache disabled when I do my tests - then of course there could be a very long discussion here - so that’s also my favorite solution.

Le 4 mars 2017 5:16 AM, “Henri Tremblay” notifications@github.com a écrit :

This is a funny issue. The problem comes from JCache mixed with the programmatic configuration.

When @MockBean is used, it forces Spring to create multiple application context. Because a context with a mock is obviously not the same as a context without the mock.

When the first context is created, it registers a CacheManager in the JCache CachingProvider. The JCacheManagerCustomizer is then called to configure this new CacheManager.

When the second context is created, it retrieves the same CacheManager since the same URI is used. And calls the JCacheManagerCustomizer again. Fail. It was working before because the ehcache.xml was loaded once and there was no customizer.

There is no way to clean the CachingProvider. @PreDestroy is called at the end of all tests. No solution there.

Using spring.cache.type=none works perfectly since it deactivate the cache. No CachingProvider issue anymore. So if we are sure we don’t want any caching during test, that’s probably a good solution. It doesn’t test the cache during testing but does remove a lot of entropy in the unit tests.

I was close to consider it a bug in spring-boot. They should not customize the CacheManager twice. But JCache gives no way to know a CacheManager was already existing.

The other solution is to check if the cache already exist.

@Beanpublic JCacheManagerCustomizer cacheManagerCustomizer() { return cm -> { createIfNotExists(cm, com.mycompany.myapp.domain.User.class.getName()); createIfNotExists(cm, com.mycompany.myapp.domain.Authority.class.getName()); createIfNotExists(cm, com.mycompany.myapp.domain.User.class.getName() + “.authorities”); createIfNotExists(cm, com.mycompany.myapp.domain.PersistentToken.class.getName()); createIfNotExists(cm, com.mycompany.myapp.domain.User.class.getName() + “.persistentTokens”); // jhipster-needle-ehcache-add-entry }; } private void createIfNotExists(CacheManager cacheManager, String cacheName) { if(cacheManager.getCache(cacheName) == null) { cacheManager.createCache(cacheName, cacheConfiguration); } }

The bad side of it is that it is production code hacked to work with tests. But it is not a none sense either.

Please tell me what you prefer and I will do a pull-request accordingly.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/jhipster/generator-jhipster/issues/5354#issuecomment-284125968, or mute the thread https://github.com/notifications/unsubscribe-auth/AATVoyHE24sDjD08g9GDzQ7X4Yfo18eRks5riOW0gaJpZM4MSueb .

Read more comments on GitHub >

github_iconTop Results From Across the Web

spring integration test fail to load context "Another resource ...
This behavior seems to indicate that using @MockBean changes the caching behavior, and each test attempts to create its own datasource. I should...
Read more >
Fix No Qualifying Spring Bean Error For Spring Boot Tests
Reasons and solutions for no qualifying Spring Bean errors when writing tests for Spring Boot applications that include a Spring Test ...
Read more >
Spring Boot Integration Testing With @SpringBootTest
If different tests need different configurations, Spring Boot cannot cache the application context and loads a new context with that configuration.
Read more >
Optimizing Spring Integration Tests - Baeldung
Every time @MockBean appears in a class, the ApplicationContext cache gets marked as dirty, hence the runner will clean the cache after the...
Read more >
Testing - Spring
The Spring TestContext Framework provides several abstract support classes that simplify the writing of integration tests. These base test ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found