Spring - Junit Test

 개발 방식중에서는 TDD(Test-driven Development)라는게 있다.

 

테스트 주도 개발에서 사용되지만 코드의 유지 보수 및 운영 환경에서의 에러를 미리 방지하기 위해서 단위 별로 검증 하는 테스트 프레임워크이다.

 

-단위테스트 : 작성한 코드가 기대하는 대로 동작하는지를 검증하는 절차

-JUnit : Java기반의 단위 테스트를 위한 프레임워크 Annotation 기반으로 테스트를 지원하며, Assert를 통하여

          (예상값, 실제값)을 통해 검증한다.

 

 

다음은 Junit을 이용해서 단위 테스트를 하는 예제 코드이다.

 

1. ICalculator 인터페이스

1
2
3
4
5
public interface ICalculator {
    int sum(int x, int y);
    int minus(int x, int y);
}
 
cs

 

2. DollarCalculator 구현클래스

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
public class DollarCalculator implements ICalculator{
    private int price = 1;
    private MarketApi marketApi;
 
    public DollarCalculator(MarketApi marketApi){ //계산기에서는 계산만 해야하므로 환율정보를 주입받도록 한다.
        this.marketApi = marketApi;
    }
 
    public void init(){
        this.price = marketApi.connect();
    }
    @Override
    public int sum(int x, int y) {
        x *= price;
        y *= price;
        return x+y;
    }
 
    @Override
    public int minus(int x, int y) {
        x *= price;
        y *= price;
        return x-y;
    }
}
 
cs

 

3. Calculator 클래스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Calculator {
 
    private ICalculator iCalculator; // 인터페이스가 필드 타입으로 사용되는 경우 
// 필드에 구현 객체를 대입할 수 있다.
 
    public Calculator(ICalculator iCalculator){ // 인터페이스가 생성자의 매개변수 타입으로 사용될 경우
// new 연산자로 객체를 생성할 때 구현 객체를 생성자의 매개값으로 대입할 수 있다.
        this.iCalculator = iCalculator;
    }
 
    public int sum(int x, int y){
        return this.iCalculator.sum(x,y);
    }
 
    public int minus(int x, int y){
        return this.iCalculator.minus(x,y);
    }
}
 
  cs

 

 

# Junit 없이 테스트한다면?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Main {
 
    public static void main(String[] args) {
        System.out.println("hello junit");
 
        Calculator calculator = new Calculator(new KrwCalculator()); //인터페이스가 필드 타입으로 사용되는 경우 필드에 구현 객체를 대입할 수 있어서 대입한 것
 
        System.out.println(calculator.sum(10,10));
 
        //dollar
 
        MarketApi marketApi = new MarketApi();
        DollarCalculator dollarCalculator = new DollarCalculator(marketApi);
        dollarCalculator.init();
 
        Calculator calculator2 = new Calculator(dollarCalculator);
        System.out.println(calculator2.sum(10,10));
    }
 
}
 
cs

junit없이 테스트를 한다고 하면 위와 같이 클래스를 콘솔에 직접 찍어서 하나하나씩 값이 맞는지 비교해야할 텐데.

아래와 같이 junit으로 단위 테스트를 진행하면 정상적으로 원하는 기대값이 출력되었는지 결과만 딱 출력해주고

테스트 히스토리와 어느 부분에서 잘못되었는지 추적하기가 용이하다.

 

#Junit으로 테스트하기

먼저 junit으로 테스트를 하기 위해서는 

@ExtendWith, @Mock, @Test 등 어노테이션을 사용한다. 이러한 어노테이션을 지원하는 라이브러리를 추가해야한다.

그 라이브러리가 바로 mokito core, mokito junit jupyter이다. 

 

아래의 링크로가서 mokito를 검색하고 저 2개를 자신의 프로젝트에 맞게(Gradle or Maven) 찾아서 복붙해주면 된다.

https://mvnrepository.com/

 

Spring Intializer를 통해서 스프링 부트를 사용해서 프로젝트를 생성했다면 기본적으로 아래 그림과 같이 자동적으로 라이브러리들이 추가되어져 있다.

하지만 자신의 프로젝트가 만약에 Spring 프로젝트가 아니라면 다음과 같이 추가해주도록 한다.

 

#Jnuit 테스트 코드

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
 
@ExtendWith(MockitoExtension.class// 모킹을 할 수 있는 환경을 만들어준다.
public class DollarCalculatorTest {
 
    @Mock
    public MarketApi marketApi; //MarketApi를 mock처리한다.
 
    @BeforeEach //test가 실행되기 이전에!
    public void init(){
        Mockito.lenient().when(marketApi.connect()).thenReturn(3000); // marketApi의 connect메소드가 실행될때 3000을 리턴시켜라.
    }
 
    @Test
    public void dollarTest(){
 
        //dollar
        MarketApi marketApi = new MarketApi(); //
        DollarCalculator dollarCalculator = new DollarCalculator(marketApi);
        dollarCalculator.init();
 
 
        Calculator calculator = new Calculator(dollarCalculator);
 
        Assertions.assertEquals(22000, calculator.sum(10,10));
        Assertions.assertEquals(0, calculator.minus(10,10));
 
    }
 
    @Test
    public void mockTest(){
        //dollar
//        MarketApi marketApi = new MarketApi(); //MarketApi를 앞에서 모킹처리해주었기 때문에 이전 주입을 위한 객체생성은 주석 처리한다.(앞에서 Befe~어노테이션에서 객체가 만들어진 상태이므로)
        DollarCalculator dollarCalculator = new DollarCalculator(marketApi);
        dollarCalculator.init();
 
        Calculator calculator = new Calculator(dollarCalculator);
        Assertions.assertEquals(60000, calculator.sum(10,10));
        Assertions.assertEquals(0, calculator.minus(10,10));
 
        System.out.println(calculator.sum(10,10));
    }
}
 
cs