반응형

테스트 케이스를 작성을 할때 내가 어렵게 생각했던것은 2가지 이다.

1. Mock 으로 테스트케이스를 작성할 것인가? 아니면 실제 데이터를 가지고 작성할 것인다.

2. 테스트용 DB를 따로 둬야 할까?

이 2가지가 항상 풀리지 않는 난제 같았다. 그런데 갑자기 뭔가 기준을 정해서 하면 되지 않을까 라는 생각이 들었다. 어떻게 보면 당연한 이야기 이긴 하지만. 테스트케이스를 작성하려는 클래스들의 역할에 생각해 보고 그에 맞는 테스트 케이스를 작성하면 되는 것이다. 

Spring Boot 프로젝트를 보면 테스트케이스를 작성하는 클래스들로 다음과 같은 것들을 꼽을 수 있다.

1. Repository
2. Service
3. Controller
4. RestApiController

그럼 우선 이번 글에서는 Repository 에 대해서만 살펴보려고 한다. Repository 는 실제로 DB 와 연결되어서 CRUD를 할 수 있는 클래스이다. Repository 클래스에 정의되어 있는 메소드를 통해서 내가 원하는 데이터를 가져올 수 있는지, 아니면 수정이 되는지 여부를 확인 하는 테스트를 작성하면 된다. 그리고 이부분은 결국 DB의 데이터가 필요하다.  Mock 으로 하기에는 실제 데이터를 가져오는지 여부가 의심(?) 스럽기 때문이다. 

@DataJpaTest
@RunWith(SpringRunner.class)
public class UserRepositoryTest {

    @Autowired
    private UserRepository userRepository;

    private Users users;
    @Before
    public void setup(){
        users = Users.builder()
                .email("test@test.com")
                .name("test")
                .status(UserStatus.APPLIED)
                .build();

        userRepository.save(users);
    }

    @Test
    public void getUsers(){
        List<Users> all = userRepository.findAll();
        Assert.assertNotNull(all);
        Assert.assertEquals(1, all.size());
    }

    @Test
    public void getUsersById(){
        Optional<Users> byId = userRepository.findById("test@test.com");
        Assert.assertNotNull(byId);
        Assert.assertEquals("test", byId.get().getName());
    }
}

@DataJpaTest 를 사용하면 테스트케이스 실행시에 MemoryDB 를 사용해서 실행을 한다.  테스트케이스를 실행해 보면 다음과 같은 로그를 볼 수 있다. 

Hibernate: drop table if exists users CASCADE 
Hibernate: create table users (email varchar(100) not null, name varchar(100) not null, user_status integer not null, primary key (email))
2021-02-17 10:56:06.114  INFO 2856 --- [    Test worker] o.h.e.t.j.p.i.JtaPlatformInitiator       : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2021-02-17 10:56:06.120  INFO 2856 --- [    Test worker] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2021-02-17 10:56:06.224  INFO 2856 --- [    Test worker] c.p.common.user.web.UserRepositoryTest   : Started UserRepositoryTest in 2.808 seconds (JVM running for 3.635)
2021-02-17 10:56:06.293  INFO 2856 --- [    Test worker] o.s.t.c.transaction.TransactionContext   : Began transaction (1) for test context [DefaultTestContext@588bc70b testClass = UserRepositoryTest, testInstance = com.polpid.common.user.web.UserRepositoryTest@4f8e0671, testMethod = getUsers@UserRepositoryTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@34cf76 testClass = UserRepositoryTest, locations = '{}', classes = '{class com.polpid.common.user.SpringCommonUserApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.autoconfigure.OverrideAutoConfigurationContextCustomizerFactory$DisableAutoConfigurationContextCustomizer@127dfcc0, org.springframework.boot.test.autoconfigure.filter.TypeExcludeFiltersContextCustomizer@351584c0, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@d5d4db2d, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@5948c9fa, [ImportsContextCustomizer@efe207e key = [org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration, org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration, org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration, org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration, org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration, org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration, org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManagerAutoConfiguration]], org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@61218ded, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@e767673, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.context.SpringBootTestArgs@1], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map[[empty]]]; transaction manager [org.springframework.orm.jpa.JpaTransactionManager@4bc55dd0]; rollback [true]
Hibernate: select users0_.email as email1_0_0_, users0_.name as name2_0_0_, users0_.user_status as user_sta3_0_0_ from users users0_ where users0_.email=?
Hibernate: insert into users (name, user_status, email) values (?, ?, ?)
Hibernate: select users0_.email as email1_0_, users0_.name as name2_0_, users0_.user_status as user_sta3_0_ from users users0_
2021-02-17 10:56:06.747  INFO 2856 --- [    Test worker] o.s.t.c.transaction.TransactionContext   : Rolled back transaction for test: [DefaultTestContext@588bc70b testClass = UserRepositoryTest, testInstance = com.polpid.common.user.web.UserRepositoryTest@4f8e0671, testMethod = getUsers@UserRepositoryTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@34cf76 testClass = UserRepositoryTest, locations = '{}', classes = '{class com.polpid.common.user.SpringCommonUserApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.autoconfigure.OverrideAutoConfigurationContextCustomizerFactory$DisableAutoConfigurationContextCustomizer@127dfcc0, org.springframework.boot.test.autoconfigure.filter.TypeExcludeFiltersContextCustomizer@351584c0, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@d5d4db2d, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@5948c9fa, [ImportsContextCustomizer@efe207e key = [org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration, org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration, org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration, org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration, org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration, org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration, org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManagerAutoConfiguration]], org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@61218ded, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@e767673, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.context.SpringBootTestArgs@1], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map[[empty]]]
2021-02-17 10:56:06.755  INFO 2856 --- [extShutdownHook] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2021-02-17 10:56:06.755  INFO 2856 --- [extShutdownHook] .SchemaDropperImpl$DelayedDropActionImpl : HHH000477: Starting delayed evictData of schema as part of SessionFactory shut-down'
Hibernate: drop table if exists users CASCADE 

 

테이블을 생성하고 Before 에 정의 되어있는 데로 데이터를 insert 한후 테스트 가 종료되면 테이블을 Drop 한다. 이정도면 Repository에 정의 되어있는 메소드가 내가 생각한대로 동작을 하는지 검증하는데는 크게 문제가 없다. 실제 DB에서 가져오도록 설정도 가능하지만 내 기준에서 테스트는 실제 DB와는 분리 되어야 한다고 생각을 하기 때문에 메모리 DB가 적합한것 같다.

한가지 주의할 점은 도메인을 정의할때 필드를 DB의 예약어와 동일하게 작성을 하면 에러가 날 수 있다. 예를 들어 order 라는 필드가 있으면 테이블이 생성될때 에러가 난다. 

org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL "create table users (email varchar(100) not null, name varchar(100) not null, order integer, user_status integer not null, primary key (email))" via JDBC Statement
	at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:67) ~[hibernate-core-5.4.18.Final.jar:5.4.18.Final]
	at org.hibernate.tool.schema.internal.SchemaCreatorImpl.applySqlString(SchemaCreatorImpl.java:439) [hibernate-core-5.4.18.Final.jar:5.4.18.Final]
	at org.hibernate.tool.schema.internal.SchemaCreatorImpl.applySqlStrings(SchemaCreatorImpl.java:423) [hibernate-core-5.4.18.Final.jar:5.4.18.Final]
	at org.hibernate.tool.schema.internal.SchemaCreatorImpl.createFromMetadata(SchemaCreatorImpl.java:314) [hibernate-core-5.4.18.Final.jar:5.4.18.Final]
	at org.hibernate.tool.schema.internal.SchemaCreatorImpl.performCreation(SchemaCreatorImpl.java:166) [hibernate-core-5.4.18.Final.jar:5.4.18.Final]
	at org.hibernate.tool.schema.internal.SchemaCreatorImpl.doCreation(SchemaCreatorImpl.java:135) [hibernate-core-5.4.18.Final.jar:5.4.18.Final]
	at org.hibernate.tool.schema.internal.SchemaCreatorImpl.doCreation(SchemaCreatorImpl.java:121) [hibernate-core-5.4.18.Final.jar:5.4.18.Final]
	at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:156) [hibernate-core-5.4.18.Final.jar:5.4.18.Final]
	at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:73) [hibernate-core-5.4.18.Final.jar:5.4.18.Final]
	at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:316) [hibernate-core-5.4.18.Final.jar:5.4.18.Final]
	at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:469) [hibernate-core-5.4.18.Final.jar:5.4.18.Final]
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1259) [hibernate-core-5.4.18.Final.jar:5.4.18.Final]
	at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:58) [spring-orm-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365) [spring-orm-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org

그렇기 때문에 이런 부분들을 조심하면 된다.

Repository 테스트에 대한 결론은 메모리 DB를 사용해서 실제 CRUD 를 테스트 해보면 된다.

이제 다음 글에서는 Service 테스트에 대해서 살펴볼 예정이다.

주의사항) 제 생각을 기준으로 작성하고 만든 소스코드이고 의견이기 때문에 틀린 부분이 있을수 있습니다.

 

728x90
반응형
반응형

Ubuntu 에서 gradle 설치를 해보자.

설치 방법은 정말 간단하다.

sudo apt-get install gradle

$ sudo apt-get install gradleReading package lists... DoneBuilding dependency tree Reading state information... DoneThe following additional packages will be installed:

이렇게 하면 설치가 쭉~~ 시작된다.

gradle -v------------------------------------------------------------Gradle 2.10------------------------------------------------------------Build time: 2016-01-26 15:17:49 UTCBuild number: noneRevision: UNKNOWNGroovy: 2.4.5Ant: Apache Ant(TM) version 1.9.6 compiled on July 20 2018JVM: 1.8.0_181 (Oracle Corporation 25.181-b13)OS: Linux 4.15.0-1021-gcp amd64

흠... 그런데... gradle 버전이 좀 이상하다.....

2.10?????

난 4 버전을 설치하고 싶은데.. 어떻게 해야하나.

sudo add-apt-repository ppa:cwchien/gradle
sudo add-apt-repository ppa:cwchien/gradle

sudo add-apt-repository ppa:cwchien/gradle

먼저 repository 를 추가한다.

그리고 sudo apt-get update 한번 쳐준다. 

sudo apt-get install gradle-4

여기까지 치고 TAB 키를 누르면

sudo apt-get install gradle-4.gradle-4.10 gradle-4.10.1 gradle-4.10.2 gradle-4.6 gradle-4.7 gradle-4.8.1 gradle-4.9

이렇게 설치할 수 있는 종류가 나온다.

나는 4.6 버전 선택해서 인스톨을 진행 했다.

gradle -v------------------------------------------------------------Gradle 4.6------------------------------------------------------------Build time: 2018-02-28 13:36:36 UTCRevision: 8fa6ce7945b640e6168488e4417f9bb96e4ab46cGroovy: 2.4.12Ant: Apache Ant(TM) version 1.9.9 compiled on February 2 2017JVM: 1.8.0_181 (Oracle Corporation 25.181-b13)OS: Linux 4.15.0-1021-gcp amd64

이렇게 설치를 마무리 하면 된다.



728x90
반응형

'Development > Build' 카테고리의 다른 글

[Gradle] gradle build error tool.jar... valid JDK  (0) 2018.10.19
Jenkins 설치  (0) 2018.09.19
Mac 에서 gradle 설치  (0) 2016.07.04
Maven 라이브러리 추출  (0) 2016.01.06
Maven clean, install, build??  (0) 2015.05.12
반응형


docker ps -a


docker stop [contatiner ID]

docker rm [containerID]

docker rmi [repositoryID]


728x90
반응형
반응형

1. 속성 정의 XML 파일에 추가되어야 하는 정의 

 xmlns:context="http://www.springframework.org/schema/context“
                                  http://www.springframework.org/schema/context
                                  http://www.springframework.org/schema/context/spring-context-3.0.xsd">  
                <context:annotation-config/>       
Spring Container가 Annotation을 인식하기 위해서는 Spring Container에 BeanPostProcessor들이 등록되어있어야한다. <context:annotation-config/>을 추가하면 내부적으로 자동 등록된다.

2. Stereotype
- @Service : Business Layer를 구성하는 서비스 클래스 대상
- @Repository : Data Access Layer를 구성하는 클래스 대상
- @Controller : 프레젠테이션 Layer를 구성하는 클래스 대상, Spring MVC 기반의 경우에 한하여 사용

3. Dependencies
- @Inject, @Autowired, @Resource : 특정 Bean의 비지니스 기능 수행을 위해 다른 Bean을 참조할경우 사용
- @Inject (javax.inject-xxx.jar)
  멤버변수, setter 메소드, 생성자, 일반 메소드에 정의
- @Autowired : Framework에 종속적
- @Resource (jsr250-api.jar)
  멤버변수와 setter 메솓에 정의할수 있음

@Inject 

 @Autowired

@Resource 

type-driven injection 방식  type-driven injection 방식  

name-matching injection 방식  

JSR-330표준, Framework에 종속되지 않음 

 Spring Framework에 종속적   JSR-2500표준, Framework에 종속되지 않음
 @Named 이용하여 특정 빈 지정

@Qualifier를 이용하여 특정 빈 지정 

 Annotation 내에 name 속성을 통해 특정 빈 지정

 멤버변수, setter메소드, 생성자, 일반메소드

   멤버변수, setter메소드, 생성자, 일반메소드    멤버변수, setter메소드

 @Inject 사용을 권장


4. Auto-Detection
- <context:component-scan> 정의 필요
- 클래스패스 상에 존재하는 클래스들을 스캔하여 Stereotype Annotation이 정의된 클래스들과 필터와 비교하여 매칭되는 클래스들을 Bean으로 인식하여 자동으로 등록

 <context:component-scan base-package="패키지명" />

5. TestCase
- @RunWith : SpringFramework에서 Junit4.5+와의 연계를 위해 제공하는 SpringJUnit4ClassRunner클래스로 정의
- @ContextConfiguration : ApplicationContext 생성시 필요한 속성정의 파일 위치 명시


728x90
반응형

'Development > Java' 카테고리의 다른 글

객체에는 메서드가 포함되지 않는다?  (0) 2013.02.12
파일 입출력.  (0) 2013.01.29
[Spring]SpEL(Spring Expression Language)  (0) 2012.07.31
[Spring]Autowiring  (0) 2012.05.03
[Spring]AOP 주요 구성요소  (0) 2012.04.13

+ Recent posts