- Update 기능 테스트 코드 만들기 -
테스트 코드를 만들던 중이었다.
member 객체를 수정하는 기능이었다.
우선 member 객체를 하나 생성한다.
그리고 DB 에 등록한다.
마지막에 등록한 member 객체를 다시 받아온다.
로컬에서 생성했던 member 객체와 DB에서 받아온 member 객체가 같은지 비교한다.
여기까지는 준비다.
이제 update 를 테스트해 보자.
DB 에서 받아온 member 객체를 수정한다.
id, psw, 생성일, 수정일 등이 있다.
모두 새로운 값으로 바꿔준다.
수정한 member 객체를 DB 에 덮어쓴다.
DB 에 덮어썼던 member 객체를 받아온다.
로컬에서 수정한 member 객체와 DB 에서 받아온 member 객체가 같은지 비교한다.
여기까지가 update 기능 테스트다.
- 로컬에서 생성한 Date 와 DB 에 들어가는 Date -
이렇게 했을 때 테스트를 통과해서 수정 기능이 제대로 작동한다고 할 수 있지 않을까?
그런데 문제가 있었다.
바로 Date 값이었다.
이상하게 DB 에 등록된 객체의 Date 값이 로컬에 있는 객체의 Date 값보다 1초 느렸다.
로컬에서 수정할 때는 5시 36분 27초였다면 DB 에 등록되는 값은 28초였다.
수정할 때보다 1초 늦은 값이 DB 에 등록됐다.
의심할 만한 구석은 하나였다.
DB 에 update 쿼리를 날릴 때 date 값을 default 로 들어가게끔 해놓았겠지.
확인해 보니 예상은 빗나갔다.
이게 웬걸, 받아온 값을 직접 넣도록 돼 있었다.
그렇다면 VO 에서 setUpdateTime() 해줄 때 어떤 로직이 있는 건 아닐까?
아무 로직도 없었다.
그냥 IDE 로 자동생성한 setter 그 자체였다.
그렇다면 체크할 때 엉뚱한 시간이랑 비교하는 건 아닐까?
분명히 member1 과 member2 두 객체의 시간을 비교하고 있었다.
그렇다면 Assertions.assertEquals() 에서 Date 자료형은 제대로 비교하지 못하는 게 아닐까?
아니다.
따로 테스트를 작성해서 확인해 보니 Date 자료형도 제대로 비교하고 있었다.
this.memberDao.updateMember(member1)
로컬에서 Date 객체를 만드는 코드와 DB에 update 를 날리는 코드 사이에 sleep 을 걸어 봤다.
member.setUpdateTime() 한 시간으로부터 5초 있다가 memberDao.updateMember() 를 실행했다.
여전히 로컬과 DB 값은 1초 차이였다.
DAO 계층이나 쿼리, DB 문제는 아니라는 뜻이었다.
- 해결 -
도대체 알 수가 없었다.
DB 도 문제가 없고
쿼리 문제도 아니고
DAO 계층도 문제가 없다.
혹시나 해서 시각을 지정한 Date() 를 만들어 봤다.
지금까지 new Date() 해서 현재 시각을 member 에 set 해줬다.
이번에는 그냥 new Date(169648451 * 1000L) 해서 시각을 고정했다.
그랬더니 이번에는 잘 됐다.
이제 보니 new Date() 라고 생성한 게 잘못됐다.
현재 시각을 Date 객체로 만들고 싶었다.
그런데 내가 생각하는 대로 작동하지는 않았다.
member.setUpdateTime(new Date()) 하면 현재 시각을 포착하여 Date 타입으로 객체를 만들고 그 안에 현재 시각이 고정으로 담길 거라고 생각했다.
그러나 실제로는 값을 불러올 때마다 현재 시각을 새로 던져줬다.
그래서 local 에서 생성했을 때와 DB에 들어갈 때 시간이 달랐던 것이다.
- 주의 -
단, 주의할 점이 있다.
new Date() 생성자 안에 숫자를 넣어주면 된다.
이 숫자는 밀리세컨드 단위이며 Long 자료형이다.
따라서 값을 세컨드 단위로 바꾸고 1000L 을 곱해주는 게 좋다.
Date 생성자에 파라미터로 밀리세컨드 단위까지 넣어주면 테스트가 실패하기 때문이다.
Assertions.assertEquals() 에서는 두 Date 객체를 비교할 때 밀리세컨드 단위까지 정확히 맞아야 한다.
하지만 DB 로부터 읽어오는 값들은 단위가 초까지만 존재한다.
따라서 로컬에서 정의하는 Date 값도 초 단위까지만 넣어주자.
그렇지 않으면 날짜와 시분초가 일치함에도 밀리세컨드 단위가 달라서 테스트에 실패한다.
@Test
public void updateMemberTest() {
//
this.memberDao.deleteAllMember();
//
MemberVO member0 = this.memberList.get(0);
this.memberDao.insertMember(member0);
int lastIndex1 = this.memberDao.getLastIndexMember();
member0.setArticleSeq(lastIndex1);
MemberVO member1 = this.memberDao.getMemberBySeq(lastIndex1);
this.checkSameMember(member0, member1);
//
String updateUserId = "updateId";
String updateUserPsw = "updatePsw";
String updateUserName = "updateName";
Date updateTime = new Date();
member1.setUserId();
member1.setUserPsw();
member1.setUserName();
member1.setCreateTime(updateTime);
member1.setUpdateTime(updateTime);
//
this.memberDao.updateMember(member1);
int lastIndex2 = this.memberDao.getLastIndexMember();
Assertions.assertEquals(lastIndex1, lastIndex2);
MemberVO member2 = this.memberDao.getMemberBySeq(lastIndex2);
//
this.checkSameMember(member1, member2);
}
public void updateMember(MemberVO member) {
this.jdbcTemplate.update(
"UPDATE TB_ARTICLE SET " +
" user_id = ?, " +
" user_psw = ?, " +
" user_name = ? , " +
" is_del = ?, " +
" create_time = ?, " +
" update_time = ? " +
"WHERE member_seq = ?",
member.getUserId(),
member.getUserPsw(),
member.getUserName(),
member.getIsDel(),
member.getCreateTime(),
member.getUpdateTime(),
member.getMemberSeq());
}
public void checkSameMember(MemberVO member1, MemberVO member2) {
Assertions.assertEquals(member1.getMemberSeq(), member2.getMemberSeq());
Assertions.assertEquals(member1.getUserId(), member2.getUserId());
Assertions.assertEquals(member1.getUserPsw(), member2.getUserPsw());
Assertions.assertEquals(member1.getUserName(), member2.getUserName());
Assertions.assertEquals(member1.getIsDel(), member2.getIsDel());
Assertions.assertEquals(member1.getCreateTime(), member2.getCreateTime());
Assertions.assertEquals(member1.getUpdateTime(), member2.getUpdateTime());
}