Spring Framework를 사용하여 테스트 프로그램을 작성하여 단위 프로그램(모듈)을 테스트 하는 방법
junit 라이브러리와 spring-test 라이브러리를 프로젝트에 빌드 처리 (메이븐 : pom.xml)
테스트 프로그램에서 사용될 로그 구현체의 환경설정파일 변경
[src/test/java] 폴더에 테스트 프로그램에 대한 클래스 작성
테스트 프로그램(JUnit) 실행 (모듈 테스트)
junit lib와 spring-test lib(Spring Framework를 이용하여 테스트 프로그램 작성에 필요한 기능을 제공) 빌드 처리
scope 속성을 주석 처리해야 테스트 프로그램 관련 클래스 작성 가능
<!-- Test -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<!-- <scope>test</scope> -->
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
<!-- => Spring Framework를 이용하여 테스트 프로그램 작성에 필요한 기능을 제공하는 라이브러리 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${org.springframework-version}</version>
<!-- <scope>test</scope> -->
</dependency>
jdbc.sqltiming : SQL 명령의 실행시간(ms) 기록
jdbc.audit : ResultSet 관련 매핑 정보를 제외한 모든 JDBC 관련 정보 기록
jdbc.resultsettable : ResultSet 관련 매핑 정보를 표(Table)형식으로 기록
jdbc.connection : Connection 객체 관련 정보 기록 (Open 또는 Close)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<!-- Appenders -->
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p: %c - %m%n" />
</layout>
</appender>
<!-- Application Loggers -->
<logger name="xyz.itwill.controller">
<level value="info" />
</logger>
<!-- 3rdparty Loggers -->
<logger name="org.springframework.core">
<level value="info" />
</logger>
<logger name="org.springframework.beans">
<level value="info" />
</logger>
<logger name="org.springframework.context">
<level value="info" />
</logger>
<logger name="org.springframework.web">
<level value="info" />
</logger>
<logger name="jdbc.sqlonly">
<level value="info" />
</logger>
<!-- jdbc.sqltiming : SQL 명령의 실행시간(ms) 기록 -->
<logger name="jdbc.sqltiming">
<level value="info" />
</logger>
<!-- jdbc.audit : ResultSet 관련 매핑 정보를 제외한 모든 JDBC 관련 정보 기록 -->
<logger name="jdbc.audit">
<level value="info" />
</logger>
<!-- jdbc.resultsettable : ResultSet 관련 매핑 정보를 표(Table)형식으로 기록 -->
<logger name="jdbc.resultsettable">
<level value="info" />
</logger>
<!-- jdbc.connection : Connection 객체 관련 정보 기록 - Open 또는 Close -->
<logger name="jdbc.connection">
<level value="info" />
</logger>
<!-- Root Logger -->
<root>
<priority value="info" />
<appender-ref ref="console" />
</root>
</log4j:configuration>
@RunWith : 테스트 프로그램의 클래스를 객체로 생성하여 테스트 메소드를 호출하기 위한 클래스를 설정하는 어노테이션
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration : 테스트 클래스에서 사용할 수 있는 Spring Bean를 제공하기 위한 Spring Bean Configuration File을 설정하는 어노테이션
@ContextConfiguration(locations = {"file:src/main/webapp/WEB-INF/spring/root-context.xml"})
테스트 클래스의 메소드에서 사용할 객체를 저장하기 위한 필드 선언
@Test : 테스트 메소드를 설정하는 어노테이션
package xyz.itwill.controller;
//@RunWith : 테스트 프로그램의 클래스를 객체로 생성하여 테스트 메소드를 호출하기 위한 클래스를
//설정하는 어노테이션 - 테스트 클래스를 실행하기 위한 클래스 설정하는 어노테이션
//value 속성 : 테스트 클래스을 실행하기 위한 클래스(Class 객체)를 속성값으로 설정
// => 다른 속성이 없는 경우 속성값만 설정 가능
//SpringJUnit4ClassRunner 클래스를 사용하여 테스트 클래스를 실행할 경우 ApplicationContext
//객체(Spring Container)가 생성되어 제공
@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration : 테스트 클래스에서 사용할 수 있는 Spring Bean를 제공하기 위한 Spring
//Bean Configuration File을 설정하는 어노테이션 - 스프링 컨테이너에 의해 관리하기 위한 객체
//locations 속성 : Spring Bean Configuration File의 경로를 요소로 저장한 배열을 속성값으로 설정
// => Spring Bean Configuration File의 경로는 file 접두사를 사용하여 파일 시스템 형식으로 표현
@ContextConfiguration(locations = {"file:src/main/webapp/WEB-INF/spring/root-context.xml"})
public class DataSourceTest {
private static final Logger logger=LoggerFactory.getLogger(DataSourceTest.class);
//테스트 클래스의 메소드에서 사용할 객체를 저장하기 위한 필드 선언
// => @AutoWired 어노테이션을 필드에 사용하여 의존성 주입 - 생성자를 이용한 의존성 주입 불가능
@Autowired
private DataSource dataSource;
//@Test : 테스트 메소드를 설정하는 어노테이션
// => SpringJUnit4ClassRunner에 의해 호출되어 모듈 테스트를 실행할 메소드
@Test
public void testDataSource() throws SQLException {
logger.info("DataSource = "+dataSource);
Connection connection=dataSource.getConnection();
logger.info("Connection = "+connection);
connection.close();
}
}
테스트 클래스의 메소드에서는 일반적으로 Service 클래스의 메소드 또는 Controller 클래스의 메소드를 호출하여 메소드가 정상적으로 동작되는지를 검사할 목적으로 작성
@WebAppConfiguration : ApplicationContext 객체가 아닌 WebApplicationContext 객체로 스프링 컨테이너 역활을 제공하도록 설정하기 위한 어노테이션
@FixMethodOrder : 테스트 메소드의 호출순서를 설정하기 위한 어노테이션
@FixMethodOrder(value = MethodSorters.NAME_ASCENDING)
package xyz.itwill.controller;
@RunWith(SpringJUnit4ClassRunner.class)
//@WebAppConfiguration : ApplicationContext 객체가 아닌 WebApplicationContext 객체로 스프링
//컨테이너 역활을 제공하도록 설정하기 위한 어노테이션
@WebAppConfiguration
@ContextConfiguration(locations = {"file:src/main/webapp/WEB-INF/spring/root-context.xml"
,"file:src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml"})
//@FixMethodOrder : 테스트 메소드의 호출순서를 설정하기 위한 어노테이션
//value 속성 : MethodSorters 자료형(Enum)의 상수 중 하나를 속성값으로 설정
// => MethodSorters.DEFAULT : JUnit 프로그램의 내부 규칙에 의해 정렬되어 메소드 호출 - 테스트마다 동일한 순서로 메소드 호출
// => MethodSorters.JVM : JVM에 의해 정렬되어 메소드 호출 - 테스트마다 변경된 순서로 메소드 호출
// => MethodSorters.NAME_ASCENDING : 테스트 메소드의 이름을 오름차순 정렬하여 메소드 호출
@FixMethodOrder(value = MethodSorters.NAME_ASCENDING)
public class StudentServiceTest {
private static final Logger logger=LoggerFactory.getLogger(StudentServiceTest.class);
@Autowired
private StudentService studentService;
@Test
public void testAddStudent() {
Student student=new Student();
student.setNo(6000);
student.setName("홍경래");
student.setPhone("010-6781-4311");
student.setAddress("서울시 중랑구");
student.setBirthday("2000-09-10");
studentService.addStudent(student);
}
@Test
public void testGetStudentList() {
List<Student> studentList=studentService.getStudentList();
for(Student student:studentList) {
//DTO 클래스의 toString() 메소드 호출 - 모든 필드값을 문자열로 변환하여 반환
logger.info(student.toString());
}
}
}
[ * ] 패턴문자를 사용하여 Spring Bean Configuration File 설정 가능
WebApplicationContext 객체를 저장하기 위한 필드 선언 (DI)
MockMvc 객체를 저장하기 위한 필드 선언
@Before : 테스트 메소드 호출 전 실행될 명령을 작성한 메소드를 설정하는 어노테이션 (초기화 작성)
MockMvcBuilders.webAppContextSetup(WebApplicationContext context)
mvc=MockMvcBuilders.webAppContextSetup(context).build();
MockMvc.perform(Builder requestBuilder) : 가상으로 페이지를 요청하는 메소드
MvcResult result=mvc.perform(MockMvcRequestBuilders.get("/student/display")).andReturn();
package xyz.itwill.controller;
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
//[*] 패턴문자를 사용하여 Spring Bean Configuration File 설정 가능
// => [**] 형식으로 0개 이상의 하위 폴더를 표현 가능
@ContextConfiguration(locations = {"file:src/main/webapp/WEB-INF/spring/**/*.xml"})
public class StudentControllerTest {
private static final Logger logger=LoggerFactory.getLogger(StudentControllerTest.class);
//WebApplicationContext 객체를 저장하기 위한 필드 선언 - DI
// => WebApplicationContext 객체 : SpringMVC 프로그램에서 스프링 컨테이너 역활을 제공하기 위한 객체
@Autowired
private WebApplicationContext context;
//MockMvc 객체를 저장하기 위한 필드 선언
// => MockMvc 객체 : 요청과 응답을 가상으로 제공하기 위한 객체
private MockMvc mvc;
//@Before : 테스트 메소드 호출 전 실행될 명령을 작성한 메소드를 설정하는 어노테이션 - 초기화 작성
@Before
public void setup() {
//MockMvcBuilders.webAppContextSetup(WebApplicationContext context)
// => MockMvcBuilder 객체를 생성하여 반환하기 위한 메소드
//MockMvcBuilder.build() : MockMvc 객체를 생성하여 반환하기 위한 메소드
mvc=MockMvcBuilders.webAppContextSetup(context).build();
logger.info("MockMvc 객체 생성");
}
@Test
public void testStudentDisplay() throws Exception {
//MockMvc.perform(Builder requestBuilder) : 가상으로 페이지를 요청하는 메소드
// => Controller 클래스에서 해당 페이지의 요청 처리 메소드 호출
// => 요청에 대한 처리결과가 저장된 ResultActions 객체 반환
//MockMvcRequestBuilders.get(String url) : URL 주소를 전달받아 GET 방식으로 요청하는 메소드
// => 페이지에 대한 URL 주소의 요청 관련 정보(리퀘스트 메세지)가 저장된 Builder 객체 반환
//ResultActions.andReturn() : 요청 처리 메소드의 실행 결과를 MvcResult 객체로 반환하는 메소드
MvcResult result=mvc.perform(MockMvcRequestBuilders.get("/student/display")).andReturn();
logger.info(result.getModelAndView().getViewName());
logger.info(result.getModelAndView().getModel().toString());
}
}