이전에 JUnit에 대한 설정 및 테스트, 실행 순서, 메서드에 대해 알아보았습니다.
그럼 실제로 사용되는 클래스를 중심으로 JUnit를 이용하여 테스트해보겠습니다.
1. "test2" 프로젝트의 "Java Resources/src/main/java"에서 "com.home.project.test2.util.MessageDigestHelper.java"를 선택하고 마우스 오른쪽 버튼을 클릭하여 콘텍스트 메뉴에서 [New > Other...]를 클릭합니다.
2. "Select a wizard"창에서 "Wizards"에 "JUnit"을 입력하고 "JUnit Test Case"를 선택한 후 "Next >"버튼을 클릭합니다.
"JUnit Test Case"창에서 "New JUnit 4 test"로 "MessageDigestHelper"에 맞게 자동으로 설정됩니다.
"Package"는 "MessageDigestHelper"와 동일한 패키지 경로로 설정되고
"Name"은 "MessageDigestHelper"에 "Test"를 붙여주고
Class under test"는 "MessageDigestHelper"의 클래스 경로로 설정되고
모든 메서드가 선택됩니다.
"Next >"버튼을 클릭합니다.
"Test Methods"창에서 단위 테스트할 메서드를 선택하고 "Finish"버튼을 클릭합니다.
"test2" 프로젝트의 [Java Resources > src/test/java]에 "com.home.project.test2.util > MessageDigestHelperTest.java"가 생성됩니다.
테스트 케이스의 주석을 보면 테스트할 메서드를 알려줍니다.
/**
* Test method for {@link com.home.project.test2.util.MessageDigestHelper#getSHA256AsBase64(java.lang.String, java.lang.String, int)}.
*/
@Test
public void testGetSHA256AsBase64() {
fail("Not yet implemented");
}
이전에 "자바 데이터베이스 매니저 패스워드 암호화 1~2"를 통해 사용자 패스워드를 암호화하였습니다.
그 당시 사용했던 패스워드와 Salt(솔트), 암호화된 패스워드를 가지고 "MessageDigestHelper"의 "getSHA256AsBase64()"메서드가 정상적으로 동작하는 테스트하기 위해 다음과 같이 "testGetSHA256AsBase64()"메서드를 수정합니다.
/**
* Test method for {@link com.home.project.test2.util.MessageDigestHelper#getSHA256AsBase64(java.lang.String, java.lang.String, int)}.
*/
@Test
public void testGetSHA256AsBase64() {
// 암호화할 패스워드
String password = "testpwd";
// 암호화 솔트
String salt ="84ebf8ab23c440a8a7cfa895f5a545f5";
// 암호화된 패스워드
String encryptionPassword = "Ti7Fm5LAk+aDnhB2BsrzINyW4c61perNa7NWLuFb2iM=";
// 테스트할 메서드
String digestPassword = MessageDigestHelper.getSHA256AsBase64(password, salt, 10);
// 메서드를 통해 암호화된 패스워드
System.out.println("digestPassword : " + digestPassword);
// 암호화된 패스워드와 메서드를 통해 암호화된 패스워드 비교
assertTrue(encryptionPassword.equals(digestPassword));
}
3. "test2" 프로젝트의 [Java Resources > src/test/java]에 있는 "com.home.project.test2.util > MessageDigestHelperTest.java"에서 마우스 오른쪽 버튼을 클릭하여 콘텍스트 메뉴에서 [Run As > JUnit Test]를 클릭합니다.
"JUnit Test"가 실행되면서 왼쪽에 "JUnit"이란 탭이 나타나고 "Error"가 "0", "Failures"이 "0"으로 예상했던 암호화된 패스워드로 나왔기 때문에 테스트가 성공합니다.
[Console]
digestPassword : Ti7Fm5LAk+aDnhB2BsrzINyW4c61perNa7NWLuFb2iM=
그럼 더 복잡한 클래스로 JUnit를 이용하여 테스트해 보겠습니다.
이전에 "자바 동적 쿼리 CRUD"에서 사용자를 조회, 등록, 수정, 삭제하는 메서드를 만든 DAO객체가 있습니다.
실제로 DAO객체의 메서드가 정상적으로 동작하는지 테스트로 확인하겠습니다.
1. "test2" 프로젝트의 "Java Resources/src/main/java"에서 "com.home.project.test2.dao.TestLoginDaoImpl.java"를 선택하고 마우스 오른쪽 버튼을 클릭하여 콘텍스트 메뉴에서 [New > Other...]를 클릭합니다.
2. "Select a wizard"창에서 "Wizards"에 "JUnit"을 입력하고 "JUnit Test Case"를 선택한 후 "Next >"버튼을 클릭합니다.
"JUnit Test Case"창에서 "TestLoginDaoImpl"에 맞게 자동으로 설정됩니다. "Next >"버튼을 클릭합니다.
"Test Methods"창에서 단위 테스트할 메서드를 선택하고 "Finish"버튼을 클릭합니다.
"test2" 프로젝트의 [Java Resources > src/test/java]에 "com.home.project.test2.dao > TestLoginDaoImplTest.java"가 생성됩니다.
현재 개발된 소스들은 Annotation(어노테인션)기반의 MVC모델로 구성되어 있습니다.
그래서 DAO 객체를 바로 생성하여 사용할 수 없습니다.
DAO 객체를 사용하기 위해 데이터 정보가 있는 프로퍼티 파일을 읽어 데이터 소스(DataSource)를 생성하고 DAO 구현체(implements)에 주입(Injection)한 후 사용할 수 있습니다.
데이터 소스 맵과 DAO 구현체(implements)를 클래스 멤버 필드에 추가합니다.
데이터 소스 맵을 사용하는 이유는 DAO 구현체(implements)에서 복수개의 데이터 소스를 사용할 수 있기 때문입니다. 여기서는 MariaDB 하나만 사용하지만 향후에 복수개를 사용할 수 있어 맵을 사용 합니다.
/**
* DBId-Database 맵
*/
private static Map<String, TestDatabaseDataSource> databaseMappingMap = null;
/**
* 로그인 DAO 구현체
*/
private static TestLoginDaoImpl testLoginDao = null;
"setUpBeforeClass()"메서드에 데이터 정보가 있는 프로퍼티 파일을 읽어 데이터 소스를 생성하고 데이터 소스 맵에 추가합니다. 그리고 생성된 DAO 구현체(implements)에 데이터 소스를 인젝션합니다.
@BeforeClass
public static void setUpBeforeClass() throws Exception {
// DBId-Database 맵
databaseMappingMap = new HashMap<String, TestDatabaseDataSource>();
// 데이터베이스 정보가 들어있는 프로퍼티파일을 읽음
// 현재 MariaDB 하나만 사용하지만 향후에 복수개가 올 수 있어 미리 준비
String databaseManagers = "/com/home/project/test2/config/database-maria.properties";
if (databaseManagers != null && !databaseManagers.trim().isEmpty()) {
String[] databaseManagerPaths = databaseManagers.trim().split("\n|,|;|\\s+");
for (String databaseManagerPath : databaseManagerPaths) {
databaseManagerPath = databaseManagerPath.trim();
if (!databaseManagerPath.isEmpty()) {
// 테이터소스 생성
TestDatabaseDataSource testDatabaseManager = new TestDatabaseDataSource(databaseManagerPath);
if (testDatabaseManager.isInitDatabasePool()) {
databaseMappingMap.put(testDatabaseManager.getId(), testDatabaseManager);
} else {
fail("테이터소스가 생성되지 못했습니다.");
}
}
}
}
assertNotNull("databaseMaria로 되는 테이터소스가 없습니다.", databaseMappingMap.get("databaseMaria"));
testLoginDao = new TestLoginDaoImpl();
assertNotNull(testLoginDao);
// 데이터소스를 DAO 클래스 맴버 필드에서 찾아 인젝션 처리
Class<?> findClass = testLoginDao.getClass();
Field[] Fields = findClass.getDeclaredFields();
for (Field field : Fields) {
TestAnnAutowired testAnnAutowired = field.getAnnotation(TestAnnAutowired.class);
TestAnnQualifier testAnnQualifier = field.getAnnotation(TestAnnQualifier.class);
if (testAnnAutowired != null && testAnnQualifier != null) {
TestDatabaseDataSource testDatabaseManager = databaseMappingMap.get(testAnnQualifier.value());
if (testDatabaseManager != null) {
field.setAccessible(true);
try {
field.set(testLoginDao, testDatabaseManager);
} catch (IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
fail("[Repository Field] " + field.getName() + "에 의존성 주입을 처리하지 못하였습니다.");
}
}
}
}
}
"tearDownAfterClass()"메서드에서 데이터 소스 맵에 있는 데이터 소스를 파괴합니다.
@AfterClass
public static void tearDownAfterClass() throws Exception {
assertNotNull(databaseMappingMap);
Iterator<String> keyIter = databaseMappingMap.keySet().iterator();
while (keyIter.hasNext()) {
String dbId = (String) keyIter.next();
TestDatabaseDataSource testDatabaseManager = databaseMappingMap.get(dbId);
testDatabaseManager.destroyDatabasePool();
}
}
"testGetMemberObject()"메서드에서 "getMemberObject()"메서드를 실행할 수 있게 수정합니다.
@Test
public void testGetMemberObject() {
System.out.println("testGetMemberObject() 테스트 시작");
UserVO userVO = new UserVO();
userVO.setId("testid");
UserVO selectUserVO = testLoginDao.getMemberObject(userVO);
System.out.println("사용자 ID : " + selectUserVO.getId());
System.out.println("사용자 이름 : " + selectUserVO.getName());
assertNotNull("데이터베이스로 부터 검색된 사용자가 없습니다.", selectUserVO);
System.out.println("testGetMemberObject() 테스트 성공 종료");
}
"testGetMemberObject()"메서드에 대한 테스트를 위해 다른 메서드들에 있는 "fail()"를 주석 처리합니다.
3. "test2" 프로젝트의 [Java Resources > src/test/java]에 있는 "com.home.project.test2.util > TestLoginDaoImplTest.java"에서 마우스 오른쪽 버튼을 클릭하여 콘텍스트 메뉴에서 [Run As > JUnit Test]를 클릭합니다.
"JUnit Test"가 실행되면서 왼쪽에 "JUnit"이란 탭이 나타나고 "Error"가 "0", "Failures"이 "0"으로 테스트가 성공합니다.
[Console]
데이터베이스 프로퍼티를 읽음
데이터베이스 커넥션 풀을 생성 시작
데이터베이스 커넥션 풀을 생성함
testGetMemberObject() 테스트 시작
[main] 데이터베이스 커넥션 객체[1076835071, URL=jdbc:mariadb://localhost:3306/test, MariaDB Connector/J]를 가져옴
PreparedStatement를 생성함
Query[sql : 'SELECT MBR_ID, MBR_PWD, MBR_PWD_SALT, MBR_NM FROM MBR_ACCOUNT_TB WHERE MBR_ID=?', parameters : ['testid']]를 실행함
PreparedStatement를 종료함
[main] 데이터베이스 커넥션 객체[1076835071, URL=jdbc:mariadb://localhost:3306/test, MariaDB Connector/J]를 반환함
21ms 소요됨
사용자 ID : testid
사용자 이름 : 홍길동
testGetMemberObject() 테스트 성공 종료
데이터베이스 커넥션 풀을 파괴함
"testGetMemberObject()"메서드에 대한 테스트가 성공적으로 처리되었습니다.
다른 메서드들도 위와 같이 테스트해보세요.