오늘은 정말 개인적으로 힘든 수업이었다. 오류가 계속해서 발생하고, 깃도 푸시가 안돼서 애를 먹었다ㅠ
오늘 수업은 JUnit 테스트! (JUnit테스트는 개발 시작 전 준비 단계이다.)
DB에 있는 데이터를 가져오기 위해서 어떤 과정이 필요할까?
원래의 개발 단계는 아래와 같다.
jsp -> controller -> service -> dao -> mapper.xml -> DB(Mysql, Oracle)
자바단위테스트인 JUnit 테스트는 jsp, controller를 하기 전에 CRUD 테스트를 하기 위함이다.
JUnit -> service -> dao -> mapper.xml -> DB
톰캣/JUnit을 실행해야만 DB가 연동되는데, 톰캣이 종료되거나 JUnit 테스트가 끝나면 DB연동이 끊어진다.
테스트하기 전, 설정해야될 것들이 있다.
스프링 테스트 pom.xml에 dependency 의존성을 추가해준다.
의존성을 추가하기에 앞서, servlet버전을 2.5 -> 3.0.1로 변경해준다.(필수)
의존성추가 1. JDBC(Java DataBase Connection) 모듈 추가 후 설정
의존성추가 2. Mysql 모듈 추가 설정
의존성추가 3. JDBC와 Mysql DB 중간에 쿼리를 사용하는 역할인 MyBatis 모듈 추가 후 설정
의존성1,2)
JDBC 모듈 추가 및 설정, Mysql 모듈 추가 및 설정을 통해 스프링에서 데이터베이스 커넥션 처리를 한다.
-> DriverManagerDataSource (DB커넥션)
의존성3)
MyBatis 모듈 추가 및 설정으로 스프링에서 쿼리를 관리하는 처리를 한다.
-> sqlSessionFactory (쿼리생성)
MyBatis에는 SELECT, INSERT, UPDATE, DELETE 쿼리를 수행하는 메소드들이 존재하는데 스프링에서 쿼리를 호출하는 메소드명(인터페이스)을 처리한다.
-> sqlSessionTemplate (쿼리호출)
DriverManagerDataSource - sqlSessionFactory - sqlSessionTemplate
JUnit 테스트 준비
src/test/java 패키지에 org.edu.test 패키지를 만들고, 그 안에 DataSourceTest.java 클래스를 만든다.
JUnit test case로 만든다. ( 그 중 JUnit 4 Test )
package org.edu.test;
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
/**
* JUnit 자바단위테스트이고, DataSource 지정 후 DB(Hsql, Mysql, Oracle) 접속,
* 데이터베이스 테이블에 Create, Read, Update, Delete 테스트용 클래스
* @author sieunlee
*
*/
@RunWith (SpringJUnit4ClassRunner.class)
@ContextConfiguration (locations= {"file:src/main/webapp/WEB-INF/spring/**/*.xml"})
@WebAppConfiguration
public class DataSourceTest {
@Test
public void test() {
//fail("Not yet implemented");
System.out.println("JUnit테스트시작");
}
}
@RunWith, @ContextConfiguration, @WebAppConfiguration 꼭 필요
pom.xml에 스프링 테스트 외부 모듈을 추가한다.
<!-- 스프링 Test사용 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${org.springframework-version}</version>
</dependency>
다음은 DB커넥션 테스트를 한다.
DB커넥션을 하기 위해서 pom.xml에 JDBC, Mysql 외부 모듈을 추가하고, MyBatis를 사용하기 위한 외부 모듈을 추가한다.
<!-- jdbc 사용 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- Mysql 데이터베이스 사용 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.35</version>
</dependency>
<!-- 마이바티스 사용 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.2.8</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.2.2</version>
</dependency>
root-context.xml에 로컬 mysql log4jdbc 설정 전 코드를 추가한다.
<!-- 로컬 mysql log4jdbc 설정전 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/edu"></property>
<property name="username" value="root"></property>
<property name="password" value="apmsetup"></property>
</bean>
DataSourceTest.java 에 테스트 코드를 추가한다.
package org.edu.test;
import static org.junit.Assert.*;
import java.sql.Connection;
import java.sql.SQLException;
import javax.inject.Inject;
import javax.sql.DataSource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
/**
* JUnit 자바단위테스트이고, DataSource 지정 후 DB(Hsql, Mysql, Oracle) 접속,
* 데이터베이스 테이블에 Create, Read, Update, Delete 테스트용 클래스
* @author sieunlee
*
*/
@RunWith (SpringJUnit4ClassRunner.class)
@ContextConfiguration (locations= {"file:src/main/webapp/WEB-INF/spring/**/*.xml"})
@WebAppConfiguration
public class DataSourceTest {
@Inject
private DataSource dataSource; // 자바에서처럼 new 키워드로 객체 생성X, 스프링에서는 @Inject로 객체 생성
@Test
public void dbConnectinoTest() throws SQLException {
// 127.0.0.1의 3306포트에 있는 DB에 커넥션해서 사용가능한지 테스트
// try-catch 구문은 테스트에서만 사용하고,
// 스프링에서는 throws Exception으로 예외를 스프링으로 보낸다.
try {
Connection connection = dataSource.getConnection();
System.out.println("DB접속 성공");
} catch (SQLException e) {
System.out.println("DB접속 실패 원인 : "+ e);
// e.printStackTrace();
}
}
}
다음은 쿼리에 관한 작업을 처리하기 위한 설정을 추가한다.
- sqlSessionFactory (쿼리생성)
root-context.xml 에 설정을 추가한다.
<!-- DataSource 설정으로 JDBC 연결후, MyBatis와 MySql을 연동시킴.
SqlSessionFactory : myBatis와 스프링의 Connection 생성후 쿼리 위치지정.-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- 매퍼 xml로만든 쿼리파일의 경로를 인식하게 함.(아래 classpath경로 src/main/resources/쿼리xml) -->
<property name="mapperLocations" value="classpath:mappers/**/*Mapper.xml"></property>
</bean>
쿼리를 모아놓는 Mapper를 생성한다.
src/main/resources 패키지 안에 mappers 폴더 내에 memberMapper.xml 파일을 생성한다.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<!--
memberMapper.xml : 회원관리에 대한 모든 쿼리를 모아서 관리하는 역할 -> MyBatis의 SessionFactory 클래스에서 쿼리를 생성한다.
이 쿼리를 호출할 때 사용하는 이름이 namespace 값이 된다.
이름이 memberMapper인 쿼리가 여러개 존재하게 되는데, 여러개를 구분해서 호출할 떄 사용하는 것이 id
-->
<mapper namespace="memberMapper">
<!-- 아래 반환값이 MemberVO 클래스형이면, select*from 쿼리에서 결과값에 [자동 바인딩]된다.
조건 : 단, 멤버클래스(MemberVO)의 멤버변수값이 tbl_member 테이블의 필드명과 일치하도록 만들어야 한다.
-->
<select id="selecMember" resultType="org.edu.vo.MemberVO">
select * from tbl_member
</select>
<!--
<insert id=""></insert>
<delete id=""></delete>
-->
</mapper>
- sqlSessionTemplate (쿼리호출)
root-context.xml 에 설정을 추가한다.
<!--
MyBatis에서 DAO를 이용하는 경우, SqlSessionTemplate라는 것을 이용해서 DAO를 구현함.
DAO라는 것은 DataAccessObject 데이터핸들링(insert(),delete()등을 처리하는 클래스 DAO라고 합니다.
개발자들이 직접 DB 연결, 종료작업하는 것을 줄여줌.
sql세션템플릿을 호출할때 SqlSessionFactory를 생성자로 주입함.
-->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate" destroy-method="clearCache">
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"></constructor-arg>
</bean>
DAO : Data Access Object-> DB의 data에 access하는 트랜잭션 객체
: DB를 사용해 데이터를 조작하는 기능을 전담하도록 만든 오브젝트
-> VO를 통해 DB의 데이터와 매칭되는 객체 생성 후 DB의 데이터를 조회, 삽입, 삭제, 갱신 가능
-> 사용자는 자신이 필요한 Interface를 DAO에게 던지고 DAO는 이 인터페이스를 구현한 객체를 사용자에게 편리하게 사용할 수 있도록 반환.
- MemberDAO 인터페이스에는 메소드를 선언만 해준다.
package org.edu.dao;
import java.util.List;
import org.edu.vo.MemberVO;
/**
* 회원관리 DAO 메소드 명세(목차) 인터페이스
* @author 이시은
*
*/
public interface IF_MemberDAO {
public List<MemberVO> selectMember() throws Exception;
// selectMember() 는 MemberMapper.class에서 정의한 select쿼리 id
}
- MemberDAOImpl 로 인터페이스(IF_MemberDAO)를 구현해주고 필요한 메소드를 오버라이드하여 정의한다.
package org.edu.dao;
import java.util.List;
import javax.inject.Inject;
import org.apache.ibatis.session.SqlSession;
import org.edu.vo.MemberVO;
import org.springframework.stereotype.Repository;
// Service나 DAO라고 어노테이션명이 되어있는 것이 아니라 Repository는 어노테이션 사용
@Repository
public class MemberDAOImpl implements IF_MemberDAO {
@Inject
private SqlSession sqlSession;
@Override
public List<MemberVO> selectMember() throws Exception {
// mapper.xml에 접근하는 방법(아래)
return sqlSession.selectList("memberMapper.selectMember");
}
}
tbl_member의 값 select 쿼리 테스트
package org.edu.test;
import static org.junit.Assert.*;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import javax.inject.Inject;
import javax.sql.DataSource;
import org.edu.dao.IF_MemberDAO;
import org.edu.vo.MemberVO;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
/**
* JUnit 자바단위테스트이고, DataSource 지정 후 DB(Hsql, Mysql, Oracle) 접속,
* 데이터베이스 테이블에 Create, Read, Update, Delete 테스트용 클래스
* @author sieunlee
*
*/
@RunWith (SpringJUnit4ClassRunner.class)
@ContextConfiguration (locations= {"file:src/main/webapp/WEB-INF/spring/**/*.xml"})
@WebAppConfiguration
public class DataSourceTest {
@Inject
IF_MemberDAO memberDAO;
@Test
public void selectMember() throws Exception {
List<MemberVO> memberList = memberDAO.selectMember();
System.out.println("회원리스트 테스트입니다.");
System.out.println(memberList.toString());
}
}
- MemberDAO 인터페이스객체를 주입한다.
- 리스트형의 memberList 변수에 selectMember라는 id를 가진 쿼리(MemberMapper에 저장)로 호출한 데이터 값(MemberVO 클래스의 데이터)을 저장한다.
- toString() 호출 -> 출력
정상 실행 된다면, toString이 두번 출력된다.
<다음 날 정리해 본 내용>
우리가 DB에서 어떻게 데이터를 가져오는지 JUnit test case를 통해 알아본다.
root-context.xml에 여러 설정을 추가, bean으로 등록 (의존성추가)
< 쿼리 실행 테스트 >
쿼리생성(mapper.xml) -> 쿼리호출메소드생성 DAO(IF_MemberDAO, MemberDAOImpl) -> 테스트(DataSourceTest.java)
'JAVA 기반 웹&앱 콘텐츠 융합 디지털 컨버전스 개발자 과정' 카테고리의 다른 글
[28일차] (0) | 2020.12.17 |
---|---|
[27일차] Service클래스 생성 및 CRUD 테스트 (0) | 2020.12.15 |
[25일차] (0) | 2020.12.13 |
[24일차] Ajax 이용한 REST API방식의 댓글 기능 구현 (0) | 2020.12.10 |
[22일차] (0) | 2020.12.08 |