스프링 빈 컨테이너에서 관리하는 빈 객체를 테스트하는 방법
1. 스프링 프레임워크를 사용하도록 기존 코드 변경하기
스프링 프레임워크를 사용하려면 관련 라이브러리들이 프로젝트에 추가 되야 한다.
pom.xml 파일을 다음과 같이 수정한다.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.edwith.webbe</groupId>
<artifactId>calculatorcli</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<failOnMissingWebXml>false</failOnMissingWebXml>
<spring.version>5.2.3.RELEASE</spring.version>
</properties>
<dependencies>
<!-- junit 4.12 라이브러리를 추가합니다. -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- spring-context와 spring-test를 의존성에 추가합니다.-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
<!-- 사용할 JDK버전을 입력합니다. JDK 11을 사용할 경우에는 1.8대신에 11로 수정합니다.--><!-- 사용할 JDK버전을 입력합니다. JDK 11을 사용할 경우에는 1.8대신에 11로 수정합니다.-->
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>utf-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
수정을 하고 나서 Maven update를 수행
스프링 프레임워크를 사용하려면 설정 파일을 작성해야 한다. 스프링 설정 파일은 xml파일이나 Java Config로 작성할 수 있다고 하였다. Java Config파일로 다음과 같이 작성해 보도록 한다.
package org.edwith.webbe.calculatorcli;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = {"org.edwith.webbe.calculatorcli"})
public class ApplicationConfig {
}
클래스 위에 @Configuration 어노테이션이 붙어 있으면 스프링 설정 파일이라는 것을 의미한다.
스프링 설정 파일은 스프링 빈 컨테이너인 ApplicationContext에서 읽어 들인다고 하였다.
@ComponentScan은 특정 패키지 이하에서 컴포넌트를 찾도록 한다.
해당 어노테이션에 설정된 패키지 이하로부터 @Component, @Repository, @Service,
@Controller, @RestController 등의 어노테이션이 붙은 클래스를 찾아 빈으로 등록한다.
package org.edwith.webbe.calculatorcli;
import org.springframework.stereotype.Component;
@Component
public class CalculatorService {
public int plus(int value1, int value2) {
return value1 + value2;
}
public int minus(int value1, int value2) {
return value1 - value2;
}
public int multiple(int value1, int value2) {
return value1 * value2;
}
public int divide(int value1, int value2) throws ArithmeticException {
return value1 / value2;
}
}
스프링 빈 컨테이너에서 관리한다는 것은 개발자가 직접 인스턴스를 생성하지 않는다는 것을 의미한다.
스프링 빈 컨테이너가 인스턴스를 생성해 관리한다는 것을 뜻한다.
스프링 빈 컨테이너가 CalculatorService클래스를 찾아 빈으로 등록할 수 있도록 클래스 위에 @Component를 붙인다.
위와 같이 작성했다면, 기존 클래스를 스프링 프레임워크에서 사용될 준비가 끝
CalculatorService 클래스를 이용하려면 다음과 같은 클래스를 작성해야 한다.
package org.edwith.webbe.calculatorcli;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Main {
public static void main(String[] args){
// ApplicationConfig.class 설정파일을 읽어들이는 ApplicationContext객체를 생성합니다.
// 아래 한줄이 실행되면서 컴포넌트 스캔을 하고, 컴포넌트를 찾으면 인스턴스를 생성하여 ApplicationContext가 관리하게 됩니다.
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ApplicationConfig.class);
// ApplicationContext가 관리하는 CalculatorService.class타입의 객체를 요청합니다.
CalculatorService calculatorService = applicationContext.getBean(CalculatorService.class);
// ApplicationContext로 부터 받은 객체를 이용하여 덧셈을 구합니다.
System.out.println(calculatorService.plus(10, 50));
}
}
Main클래스를 실행하면 결과는 60이 출력,. 설명은 주석문을 참고
2. 테스트 클래스를 스프링 빈 컨테이너를 사용하도록 수정하기
기존 테스트 클래스는 테스트할 객체를 @Before가 붙은 메소드에서 초기화 하였다.
스프링 빈 컨테이너를 사용할 때는 개발자가 직접 인스턴스를 생성하면 안된다.
스프링 빈 컨테이너가 빈을 생성하고 관리하도록 하고, 그 빈을 테스트 해야한다.
이를 위해서 스프링 프레임워크는 몇가지 특별한 기능을 제공합니다. 소스 코드를 아래와 같이 수정하도록 한다.
package org.edwith.webbe.calculatorcli;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {ApplicationConfig.class})
public class CalculatorServiceTest {
@Autowired
CalculatorService calculatorService;
@Test
public void plus() throws Exception{
// given
int value1 = 10;
int value2 = 5;
// when
int result = calculatorService.plus(value1, value2);
// then
Assert.assertEquals(result, 15); // 결과와 15가 같을 경우에만 성공
}
@Test
public void divide() throws Exception{
// given
int value1 = 10;
int value2 = 5;
// when
int result = calculatorService.divide(value1, value2);
// then
Assert.assertEquals(result, 2); // 결과와 15가 같을 경우에만 성공
}
@Test
public void divideExceptionTest() throws Exception{
// given
int value1 = 10;
int value2 = 0;
try {
calculatorService.divide(value1, value2);
}catch (ArithmeticException ae){
Assert.assertTrue(true); // 이부분이 실행되었다면 성공
return; // 메소드를 더이상 실행하지 않는다.
}
Assert.fail(); // 이부분이 실행되면 무조건 실패다.
}
}
기존 테스트 클래스 위에 @RunWith(SpringJUnit4ClassRunner.class)를 붙인다.
@RunWith 어노테이션은 JUnit이 제공하는 어노테이션이다.
JUnit은 확장기능을 가지는데, 스프링에서는 JUnit을 확장하도록 SpringJUnit4ClassRunner.class를 제공한다.
해당 코드는 JUnit이 테스트 코드를 실행할 때 스프링 빈 컨테이너가 내부적으로 생성되도록 한다.
@ContextConfiguration(classes = {ApplicationConfig.class})은 내부적으로 생성된 스프링 빈 컨테이너가
사용할 설정파일을 지정할 때 사용한다.
위에서 설명한 2줄이 테스트 클래스 위에 있으면, 테스트 클래스 자체가 빈(Bean)객체가 되어 스프링에서 관리되게 된다.
@Autowired
CalculatorService calculatorService;
CalcultorServiceTest 클래스가 빈으로 관리되면서, 스프링 빈 컨테이너는 CalculatorService를
주입(Inject)할 수 있게 됩니다. 이렇게 주입된 클래스를 테스트하면 된다.
테스트 결과는 기존의 클래스와 같은 것을 확인할 수 있다.