Home 테스트 하기 좋은 코드에 대한 가벼운 단상
Post
Cancel

테스트 하기 좋은 코드에 대한 가벼운 단상

테스트 하기 좋은 코드에 관한 가벼운 단상

개요

JWT(Json Web Token)을 생성하고, 검증하는 유틸성 클래스를 개발하고 테스트 코드를 작성하는 도중에 토큰 만료에 대한 검증로직을 테스트 해야했다.
토큰 만료에 대한 검증을 하기 위해서는 만료시간이 지난 토큰을 생성해내고, 만료 검증 로직이 통과되는지, 안되는지에 대해서 간단하게 확인하면 된다.

토큰을 생성하는 코드 - 수정 전

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class JwtUtils{
    ...
    public String createToken(Map<String, Object> payload) {

        Claims claims = Jwts.claims(payload);
        Date now = new Date();
        Date expiration = new Date(now.getTime() + validityInMilliseconds);

        return Jwts.builder()
                .setClaims(claims)
                .setIssuedAt(now)
                .setExpiration(expiration)
                .signWith(SignatureAlgorithm.HS256, secretKey)
                .compact();
    }
    ...
}

class JwtUtils{
    @Test
    void validateToken(){
        ...
        String token = jwtUtils.createToken(payload); // 매번 테스트 코드가 실행되는 시점이 issuedAt으로 설정되어 토큰 생성
        ...
    }
}

하지만 테스트 코드를 작성하려고 보니, 현재 토큰을 생성하는 로직이 함수내에서 new Data()를 통해서 현재 시각를 가져오고 거기에 미리 설정해놓은 유효기간을 더해서 토큰을 생성하게끔 되어있다. 함수구조가 이렇게 되어있으면 테스트 코드단에서 이미 만료된 토큰을 생성하는게 쉽지가 않다.

토큰을 생성하는 코드 - 수정 후

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class JwtUtils{
    ...
    public String createToken(Map<String, Object> payload, Date issuedAt) {

        Claims claims = Jwts.claims(payload);
        Date expiration = new Date(issuedAt.getTime() + validityInMilliseconds);

        return Jwts.builder()
                .setClaims(claims)
                .setIssuedAt(issuedAt)
                .setExpiration(expiration)
                .signWith(SignatureAlgorithm.HS256, secretKey)
                .compact();
    }
    ...
}

class JwtUtils{
    @Test
    void validateToken(){
        ...
        LocalDateTime issuedAtDateTime = LocalDateTime.of(2023, Month.MAY, 1, 06, 30);
        Date issuedAt = Timestamp.valueOf(issuedAtDateTime);
        String token = jwtUtils.createToken(payload, issuedAt); // 매번 테스트 코드가 실행되는 시점이 issuedAt으로 설정되어 토큰 생성
        ...
    }
}

테스트를 위해서 토큰 발급일을 결정하는 Date 변수를 메소드의 파라미터로 분리했다.
수정 전 createToken 메소드는 현재 시점을 기준을 토큰을 발급 하는 함수 였지만,
변경 후에는 원하는 시점을 기준으로 토큰을 발급 하는 함수가 되었다.

가장 큰 차이점은 발급일을 개발자가 제어할 수 있다는 점이다.

최대한 개발자가 많은 것을 제어할 수 있는 환경일 수록 테스트가 쉽다고 생각한다.
외부 API 처럼 직접 코드를 수정할 수 없고 제어할 수 없는 경우에는 test double이나 mockwebserver 등으로 제어하는 척을 하면서 테스트를 하게 된다.
하지만 이처럼 내부 코드내에서는 개발자가 최대한 제어할 수 있는 구조로 코드가 구성이 필요하다고 생각한다.

관련해서 좋은 글과 유튜브 영상을 알게 되었고 참조해보면 좋을 것 같다.

This post is licensed under CC BY 4.0 by the author.

스프링에서 embedded redis 테스트 환경 구축하기

submodule로 민감정보 관리하기