어렴풋이 생각은 해봤었는데, 이번 기회에 정리해 보네요. 매우 주관적이며 OSAF 프레임워크를 사용하는 경우에 해당하는 가이드이기 때문에 통용될리는 없다고 생각합니다. 하지만 적어도 저한테는 이렇게 하는 것이 타당해 보이며, 조금만 응용하면, 다른 프레임워크 또는 별도의 프레임워크가 없는 경우에도 어느정도 적절할 것으로 보입니다. 그럼.. 차근차근 정리해 보겠습니다.

DAO 통합 테스트

DAO 테스트는 항상 데이터베이스를 필요로 하기 때문에 통합 테스트로 볼 수 있습니다.

테스트하지 않을 것

  • 프레임워크 코드

OSAF의 GenericDao로부터 상속받은 코드와 하이버네이트 코드는 테스트하지 않습니다.

테스트 할 것

  • 하이버네이트 도메인 모델 검증

도메인 모델에 맵핑 정보가 제대로 설정되었는지 확인합니다.
OSAF GenericDao가 제공하는 save로 도메인 모델을 저장해보는 것으로 확인합니다.

	@Test
public void crud() throws Exception {
Code code = new Code();
code.setCodeCate(CodeCate.CAR_TYPE);
code.setName("BLK");

cd.save(code);
}
  • DAO에서 재정의하는(overriding)하는 addRestrictions 메서드

해당 메서드에서 정의하는 검색 조건과 정렬 옵션에 따른 쿼리가 제대로 동작하는지 테스트 합니다.

	protected Criteria addRestrictions(Criteria c, CodeParams params) {
CriteriaUtils.ilike(c, "name", params.getName(), MatchMode.ANYWHERE);
CriteriaUtils.conditionalEq(c, "codeCate", params.getCodeCate());
c.addOrder(Order.asc("codeCate"));
return c;
}
  • DAO 인터페이스에 별도로 추가한 메서드의 구현체

OSAF에서 상속받지 않은 코드로, DAO 인터페이스에 추가하고, DaoImpl 클래스에서 구현한 메서드도 테스트가 필요합니다.

//DAO 인터페이스
public interface CodeDao extends GenericDao<Code, CodeParams> {
public List<Code> findByCodeCate(CodeCate codeCate);
}

//DAO 인터페이스 구현체
@Repository
public class CodeDaoImpl extends GenericDaoImpl<Code, CodeParams> implements CodeDao{

...

@SuppressWarnings("unchecked")
public List<Code> findByCodeCate(CodeCate codeCate){
return super.getSession().createCriteria(Code.class).add(
Restrictions.eq("codeCate", codeCate)).list();
}

}

테스트 코드 작성 방법

  • 스프링 @Test 선언

애노테이션 추가: DAO 테스트에 스프링 테스트 러너, 설정 파일 위치, 트랜잭션을 설정합니다.

테스트 설정 파일 위치: 테스트용 스프링 설정파일은 test 폴터 밑에 위치한 testApplicationContext.xml을 사용합니다.

트랜잭션 설정: OSAF의 DAO는 트랜잭션 당 세션을 유지하기 위해 getCurrentSession()을 사용하고 있기 때문에 @Transactional을 반드시 추가해야 합니다.

테스트 클래스 이름: 테스트할 DAO 구현체 이름뒤에 Test를 붙여서 작명합니다.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="/testApplicationContext.xml")
@Transactional()
public class CodeDaoImplTest {

}
  • DBUnitSupport 클래스 상속.

DBUnit을 편하게 사용할 수 있도록 DBUbnitSupport 클래스를 상속 받습니다.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="/testApplicationContext.xml")
@Transactional()
public class CodeDaoImplTest extends DBUnitSupport{

}
  • 테스트 데이터를 적성합니다.

XML 테스트 데이터가 필요한 경우 테스트 클래스와 동일한 패키지에 두어 접근성을 높여줍니다.
XML 테스트 데이터는 다음과 같이 작성합니다.

<dataset>
<code id="1" name="test" codeCate="10" />
<code id="2" name="test" codeCate="10" />
<code id="3" name="test" codeCate="20" />
<code id="4" name="test" codeCate="20" />
</dataset>
  • 테스트를 작성합니다.

테스트 데이터가 필요한 테스트는 DBUnitSupport에서 상속받은 insertXmlData();
또는 inserXlsData(); 메서드를 이용하여 테스트 데이터를 넣어줍니다.

	@Test
public void search() throws Exception {
insertXmlData("testData.xml");
CodeParams params = new CodeParams();
OrderPage orderPage = new OrderPage();

params.setName("te");
assertThat(cd.search(params, orderPage).size(), is(4));

params.setName("");
params.setCodeCate(PersistentEnumUtil.valueOf(CodeCate.class, 20));
assertEquals(2, cd.search(params, orderPage).size());
}

생각해볼 것

  • 테스트 데이터베이스와 실제 데이터페이스가 다르다

배포용으로는 MySQL을 사용하면서 테스트할 때는 HSQL을 사용한다. 과연 제대로 테스트 했다고 볼 수 있을까?