DataSourceConfig에서 @EnableTransactionManagement를 사용하면 DataSourceTest가 안 되는것에 대한 질문이 있습니다.
안녕하세요 토비님. 강의 정말 잘 듣고있습니다! JdbcTemplate과 트랜잭션 매니저 구성 강의를 듣다가 @EnableTransactionManagement으로 트랜잭션(tx) 관리 기능을 열어주고 기존 DataSourceTest.java 예제를 실행하니 java.lang.IllegalStateException: Failed to unwrap proxied object 에러가 계속 발생합니다.DataSourceConfig.java에서 @EnableTransactionManagement 애노테이션을 제외를 하면 DataSourceTest.java 테스트가 정상적으로 잘 돌아가더라고요...음 java와 spring 버전, 라이브러리는 모두 동일하게 설정을 했습니다. 제 소스 코드는 하단에 있습니다! 버전 문제로 해당 예제가 안 돌아가는 것인지? 왜 안 되는지 궁금합니다.. 바쁘실텐데 이유나 원인을 아시면 알려주시면 감사하겠습니다. 에러코드java.lang.IllegalStateException: Failed to unwrap proxied object
at org.springframework.test.util.AopTestUtils.getUltimateTargetObject(AopTestUtils.java:105)
at org.springframework.boot.test.mock.mockito.SpringBootMockResolver.resolve(SpringBootMockResolver.java:35)
at org.mockito.internal.util.MockUtil.resolve(MockUtil.java:118)
at org.mockito.internal.util.MockUtil.isMock(MockUtil.java:108)
at org.mockito.internal.util.DefaultMockingDetails.isMock(DefaultMockingDetails.java:32)
at org.springframework.boot.test.mock.mockito.MockReset.get(MockReset.java:106)
at org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener.resetMocks(ResetMocksTestExecutionListener.java:82)
at org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener.resetMocks(ResetMocksTestExecutionListener.java:70)
at org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener.beforeTestMethod(ResetMocksTestExecutionListener.java:57)
at org.springframework.test.context.TestContextManager.beforeTestMethod(TestContextManager.java:293) build.gradleplugins {
id 'java'
id 'org.springframework.boot' version '2.7.6'
id 'io.spring.dependency-management' version '1.0.15.RELEASE'
}
group = 'tobyspring'
version = '0.0.1-SNAPSHOT'
java {
sourceCompatibility = '11'
}
repositories {
mavenCentral()
maven {
url 'https://repo.clojars.org'
name 'Clojars'
}
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework:spring-jdbc'
implementation 'hikari-cp:hikari-cp:3.0.1'
runtimeOnly('com.h2database:h2:2.1.214')
// spring-boot-starter-undertow
// implementation 'org.springframework.boot:spring-boot-starter-jetty'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
tasks.named('test') {
useJUnitPlatform()
}
DataSourceTest
package tobyspring.helloboot;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
@HellobootTest
public class DataSourceTest {
@Autowired
DataSource dataSource;
@Test
public void connect() throws SQLException {
Connection connection = dataSource.getConnection();
connection.close();
}
} HelloBootTestpackage tobyspring.helloboot;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.transaction.annotation.Transactional;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = HellobootApplication.class)
@TestPropertySource("classpath:/application.properties")
@Transactional
public @interface HellobootTest {
}
DataSourceConfig.javapackage tobyspring.config.autoconfig.datasource;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
import org.springframework.jdbc.support.JdbcTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import tobyspring.config.ConditionalMyOnClass;
import tobyspring.config.MyAutoConfiguration;
import tobyspring.config.autoconfig.EnableMyConfigurationProperties;
import javax.sql.DataSource;
import java.sql.Driver;
@MyAutoConfiguration
@ConditionalMyOnClass("org.springframework.jdbc.core.JdbcOperations")
@EnableMyConfigurationProperties(MyDataSourceProperties.class)
@EnableTransactionManagement
public class DataSourceConfig {
@Bean
@ConditionalMyOnClass("com.zaxxer.hikari.HikariDataSource")
@ConditionalOnMissingBean
DataSource hikariDataSource(MyDataSourceProperties properties) {
HikariDataSource dataSource = new HikariDataSource();
dataSource.setDriverClassName(properties.getDriverClassName());
dataSource.setJdbcUrl(properties.getUrl());
dataSource.setUsername(properties.getUsername());
dataSource.setPassword(properties.getPassword());
return dataSource;
}
@Bean
@ConditionalOnMissingBean
DataSource dataSource(MyDataSourceProperties properties) throws ClassNotFoundException {
SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
dataSource.setDriverClass((Class<? extends Driver>) Class.forName(properties.getDriverClassName()));
dataSource.setUrl(properties.getUrl());
dataSource.setUsername(properties.getUsername());
dataSource.setPassword(properties.getPassword());
return dataSource;
}
@Bean
@ConditionalOnSingleCandidate(DataSource.class)
@ConditionalOnMissingBean
JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
@Bean
@ConditionalOnSingleCandidate(DataSource.class)
@ConditionalOnMissingBean
JdbcTransactionManager jdbcTransactionManager(DataSource dataSource) {
return new JdbcTransactionManager(dataSource);
}
}