문제
스프링 미션을 진행하던 중 단위 테스트는 잘 수행되었으나 통합테스트가 에러가 났다.
java.lang.IllegalStateException: Failed to load ApplicationContext
Failed to load ApplicationContext
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:98)
~~~
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'webController' defined in file [/Users/donghae/Desktop/study/jwp-racingcar/build/classes/java/main/racingcar/controller/WebController.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'gameService' defined in file [/Users/donghae/Desktop/study/jwp-racingcar/build/classes/java/main/racingcar/service/GameService.class]: Unsatisfied dependency expressed through constructor parameter 1; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'inMemoryCarDao' defined in file [/Users/donghae/Desktop/study/jwp-racingcar/build/classes/java/main/racingcar/dao/InMemoryCarDao.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSourceScriptDatabaseInitializer' defined in class path resource [org/springframework/boot/autoconfigure/sql/init/DataSourceInitializationConfiguration.class]: Invocation of init method failed; nested exception is org.springframework.jdbc.datasource.init.ScriptStatementFailedException: Failed to execute SQL script statement #1 of URL [file:/Users/donghae/Desktop/study/jwp-racingcar/build/resources/main/data.sql]: CREATE TABLE PLAY_RESULT ( id INT NOT NULL AUTO_INCREMENT, trial_count INT NOT NULL, winners VARCHAR(50) NOT NULL, created_at DATETIME NOT NULL default current_timestamp, PRIMARY KEY (id) ); nested exception is org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "PLAY_RESULT" already exists; SQL statement:
CREATE TABLE PLAY_RESULT ( id INT NOT NULL AUTO_INCREMENT, trial_count INT NOT NULL, winners VARCHAR(50) NOT NULL, created_at DATETIME NOT NULL default current_timestamp, PRIMARY KEY (id) ) [42101-214]
~~~
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'gameService' defined in file [/Users/donghae/Desktop/study/jwp-racingcar/build/classes/java/main/racingcar/service/GameService.class]: Unsatisfied dependency expressed through constructor parameter 1; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'inMemoryCarDao' defined in file [/Users/donghae/Desktop/study/jwp-racingcar/build/classes/java/main/racingcar/dao/InMemoryCarDao.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSourceScriptDatabaseInitializer' defined in class path resource [org/springframework/boot/autoconfigure/sql/init/DataSourceInitializationConfiguration.class]: Invocation of init method failed; nested exception is org.springframework.jdbc.datasource.init.ScriptStatementFailedException: Failed to execute SQL script statement #1 of URL [file:/Users/donghae/Desktop/study/jwp-racingcar/build/resources/main/data.sql]: CREATE TABLE PLAY_RESULT ( id INT NOT NULL AUTO_INCREMENT, trial_count INT NOT NULL, winners VARCHAR(50) NOT NULL, created_at DATETIME NOT NULL default current_timestamp, PRIMARY KEY (id) ); nested exception is org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "PLAY_RESULT" already exists; SQL statement:
CREATE TABLE PLAY_RESULT ( id INT NOT NULL AUTO_INCREMENT, trial_count INT NOT NULL, winners VARCHAR(50) NOT NULL, created_at DATETIME NOT NULL default current_timestamp, PRIMARY KEY (id) ) [42101-214]
~~~
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'inMemoryCarDao' defined in file [/Users/donghae/Desktop/study/jwp-racingcar/build/classes/java/main/racingcar/dao/InMemoryCarDao.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSourceScriptDatabaseInitializer' defined in class path resource [org/springframework/boot/autoconfigure/sql/init/DataSourceInitializationConfiguration.class]: Invocation of init method failed; nested exception is org.springframework.jdbc.datasource.init.ScriptStatementFailedException: Failed to execute SQL script statement #1 of URL [file:/Users/donghae/Desktop/study/jwp-racingcar/build/resources/main/data.sql]: CREATE TABLE PLAY_RESULT ( id INT NOT NULL AUTO_INCREMENT, trial_count INT NOT NULL, winners VARCHAR(50) NOT NULL, created_at DATETIME NOT NULL default current_timestamp, PRIMARY KEY (id) ); nested exception is org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "PLAY_RESULT" already exists; SQL statement:
CREATE TABLE PLAY_RESULT ( id INT NOT NULL AUTO_INCREMENT, trial_count INT NOT NULL, winners VARCHAR(50) NOT NULL, created_at DATETIME NOT NULL default current_timestamp, PRIMARY KEY (id) ) [42101-214]
~~~
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSourceScriptDatabaseInitializer' defined in class path resource [org/springframework/boot/autoconfigure/sql/init/DataSourceInitializationConfiguration.class]: Invocation of init method failed; nested exception is org.springframework.jdbc.datasource.init.ScriptStatementFailedException: Failed to execute SQL script statement #1 of URL [file:/Users/donghae/Desktop/study/jwp-racingcar/build/resources/main/data.sql]: CREATE TABLE PLAY_RESULT ( id INT NOT NULL AUTO_INCREMENT, trial_count INT NOT NULL, winners VARCHAR(50) NOT NULL, created_at DATETIME NOT NULL default current_timestamp, PRIMARY KEY (id) ); nested exception is org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "PLAY_RESULT" already exists; SQL statement:
CREATE TABLE PLAY_RESULT ( id INT NOT NULL AUTO_INCREMENT, trial_count INT NOT NULL, winners VARCHAR(50) NOT NULL, created_at DATETIME NOT NULL default current_timestamp, PRIMARY KEY (id) ) [42101-214]
~~~
Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "PLAY_RESULT" already exists; SQL statement:
CREATE TABLE PLAY_RESULT ( id INT NOT NULL AUTO_INCREMENT, trial_count INT NOT NULL, winners VARCHAR(50) NOT NULL, created_at DATETIME NOT NULL default current_timestamp, PRIMARY KEY (id) ) [42101-214]
~~~
처음에는 에러가 엄청 길다 보니 bean을 생성하지 못하네? 왜 못하지 ? 라는 생각을 하였다.
하지만 잘 살펴보니 아래와 같은 에러를 보았다.
Table "PLAY_RESULT" already exists;
원인
여러 통합 테스트의 @SpringBootTest 는 여러개의 ApplicationContext를 생성한다. 나의 테스트 에서는 이 각각의 SpringBootTest가 있었는데 이럴 경우 RandomPort가 생성되어 웹환경을 구축하고, None으로 웹환경을 구축하기에 각각의 ApplicationContext이 생성된다.
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
그 경우 나처럼 db를 사용중이면 resource에 있는 data.sql로 db를 생성초기화 한다.
하지만 JVM에는 이미 db가 올라가 있고 그 밑단에서 새롭게 db를 생성하려고 하니 에러가 발생하는 것이다 !
나는 분명 테스트코드에서 BeforeEach로 계속 테이블을 drop해주었는데 왜 안되지 ? 라는 의문을 계속 가졌다.
이 의문에 대한 해결은 beforeEach가 돌기도 전에 ApplicationContext생성될때 에러를 띄우기에 작동조차 하지 않았던 것이다 ....
해결
CREATE TABLE IF NOT EXISTS CAR_RESULT (
);
위와 같이 Sql문에서 재생성 불가하게 막았다.
'코코코딩공부 > Spring' 카테고리의 다른 글
[Spring] Dispatcher Servlet이란 ? & 미션 에서 찾아보기 (0) | 2023.04.30 |
---|---|
[Spring] Servlet 이란 ? (0) | 2023.04.30 |
[Spring] 어떤 객체를 빈으로 등록해야 할까 ? (1) | 2023.04.23 |
[Spring] Bean 이란 ? (0) | 2023.04.23 |
[Architecture] Layered Architecture (3) | 2023.04.15 |