Home > database >  Java 17, Spring boot test, @Sql script exception
Java 17, Spring boot test, @Sql script exception

Time:11-24

After upgrade to java 17, spring boot 2.5.5 I cannot use @Sql script

This is my test class:

@RunWith(SpringRunner.class)
@ActiveProfiles("test")
@SpringBootTest(classes = {App.class})
@ContextConfiguration(loader = CustomContextLoaderProvider.CustomContextLoader.class)
@SuppressWarnings("Duplicates")
@Sql(scripts = "/clear_data.sql", executionPhase = ExecutionPhase.AFTER_TEST_METHOD)
public class ApiControllerTest {...}

And context loader provider for postgres test containers

public class CustomContextLoaderProvider {

  private static final PostgreSQLContainer postgres = new PostgreSQLContainer("postgres:10.5");

  static {
    postgres.start();
    Runtime.getRuntime().addShutdownHook(new Thread(postgres::stop));
 }

  public static class CustomContextLoader extends SpringBootContextLoader {

    @Override
    protected String[] getInlinedProperties(MergedContextConfiguration config) {
      return ArrayUtils.addAll(
          super.getInlinedProperties(config),
          "spring.datasource.url="   postgres.getJdbcUrl(),
          "spring.datasource.username="   postgres.getUsername(),
          "spring.datasource.password="   postgres.getPassword());
    }
  }
}

stacktrace:

  Failed to execute SQL scripts for test context [DefaultTestContext@19553973 testClass = ApiControllerTest, testInstance = ApiControllerTest@9af804b, testMethod = delete@ApiControllerTest, testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@7bb6ab3a testClass = ApiControllerTest, locations = '{}', classes = '{class App}', contextInitializerClasses = '[]', activeProfiles = '{test}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.autoconfigure.actuate.metrics.MetricsExportContextCustomizerFactory$DisableMetricExportContextCustomizer@2bec854f, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@2a7ed1f, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@5f0fd5a0, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@4fa1c212, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@1cb346ea, org.springframework.boot.test.context.SpringBootTestArgs@1, org.springframework.boot.test.context.SpringBootTestWebEnvironment@6f204a1a], resourceBasePath = 'src/main/webapp', contextLoader = 'CustomContextLoaderProvider$CustomContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.populatedRequestContextHolder' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.resetRequestContextHolder' -> true, 'org.springframework.test.context.event.ApplicationEventsTestExecutionListener.recordApplicationEvents' -> false]]: the configured DataSource [jdk.proxy3.$Proxy138] (named '') is not the one associated with transaction manager [org.springframework.orm.jpa.JpaTransactionManager] (named '').
    java.lang.IllegalStateException: Failed to execute SQL scripts for test context [DefaultTestContext@19553973 testClass = ApiControllerTest, testInstance = ApiControllerTest@9af804b, testMethod = delete@ApiControllerTest, testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@7bb6ab3a testClass = ApiControllerTest, locations = '{}', classes = '{class App}', contextInitializerClasses = '[]', activeProfiles = '{test}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.autoconfigure.actuate.metrics.MetricsExportContextCustomizerFactory$DisableMetricExportContextCustomizer@2bec854f, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@2a7ed1f, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@5f0fd5a0, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@4fa1c212, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@1cb346ea, org.springframework.boot.test.context.SpringBootTestArgs@1, org.springframework.boot.test.context.SpringBootTestWebEnvironment@6f204a1a], resourceBasePath = 'src/main/webapp', contextLoader = 'CustomContextLoaderProvider$CustomContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.populatedRequestContextHolder' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.resetRequestContextHolder' -> true, 'org.springframework.test.context.event.ApplicationEventsTestExecutionListener.recordApplicationEvents' -> false]]: the configured DataSource [jdk.proxy3.$Proxy138] (named '') is not the one associated with transaction manager [org.springframework.orm.jpa.JpaTransactionManager] (named '').
    at org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener.executeSqlScripts(SqlScriptsTestExecutionListener.java:263)
    at org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener.lambda$executeSqlScripts$0(SqlScriptsTestExecutionListener.java:201)
    at java.base/java.lang.Iterable.forEach(Iterable.java:75)
    at org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener.executeSqlScripts(SqlScriptsTestExecutionListener.java:201)
    at org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener.executeSqlScripts(SqlScriptsTestExecutionListener.java:148)
    at org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener.afterTestMethod(SqlScriptsTestExecutionListener.java:127)
    at org.springframework.test.context.TestContextManager.afterTestMethod(TestContextManager.java:445)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:94)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
    at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
    at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:110)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38)
    at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:62)
    at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
    at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
    at jdk.proxy1/jdk.proxy1.$Proxy2.processTestClass(Unknown Source)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run(TestWorker.java:176)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
    at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
    at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:133)
    at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
    at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
    at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)

this exception throws here (SqlScriptsTestExecutionListener):

if (dataSource != null && dataSourceFromTxMgr != null && !sameDataSource(dataSource, dataSourceFromTxMgr)) {
            throw new IllegalStateException(String.format("Failed to execute SQL scripts for test context %s: "  
                    "the configured DataSource [%s] (named '%s') is not the one associated with "  
                    "transaction manager [%s] (named '%s').", testContext, dataSource.getClass().getName(),
                    dsName, txMgr.getClass().getName(), tmName));
        }

dataSource and dataSourceFromTxMgr, are equals, but they are both proxies, so when .equals method is invoked, it compare real object with proxy(which of course returns false)

I try to debug this exception and found the cause. The problem can be in JpaTransactionManager. For some reason dataSource is proxy object whereas in old version datasource was real hikari datasource. I am not sure that is it a real problem and I have no ideas how to fix it

CodePudding user response:

The problem was in javaMelody. Java melody creates proxy for everything, so i excluded it spring boot autoconfiguration and it works

In the application-test.properties I added this:

spring.autoconfigure.exclude=net.bull.javamelody.JavaMelodyAutoConfiguration

  • Related