[Spring , Java] JUnit에 대하여

JUnit에 대하여



프로그램을 작성하면서 가장 필요한 것은 내가 만든 코드가 정상적으로 작동하는지 테스트하는 것이다.
하지만 매번 많은 코드를 테스트 하기에는 많은 시간을 필요로한다. 
그래서 코드를 작성을 할때는 코드를 항상 단위적으로 나눠서 단위테스트를 하는게 가장 좋은 방법이다.
오늘은 내가 작성한 코드를 어떠한 방법으로 테스트 할것인지 알아볼 것이다. 

JUnit은 간단하면서 반복적인 테스트를 실행할 수 있는 오픈소스 프레임워크이다.


필요한 Maven 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
        <!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>
        
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>4.3.18.RELEASE</version>
    <scope>test</scope>
</dependency>
cs

매처를 위한 Maven 
<!-- https://mvnrepository.com/artifact/org.hamcrest/hamcrest-all -->
<dependency>
    <groupId>org.hamcrest</groupId>
    <artifactId>hamcrest-all</artifactId>
    <version>1.3</version>
    <scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hamcrest/hamcrest-core -->
<dependency>
    <groupId>org.hamcrest</groupId>
    <artifactId>hamcrest-core</artifactId>
    <version>1.3</version>
    <scope>test</scope>
</dependency>
cs


Junit은 버전 4로 이용할 것이다.
JUnit을 사용하기 앞서 프로젝트에 JUnit을 추가하는 과정을 해줘야 한다.








이제 테스트를 할 수 있게 되었다.
가장 기본적인 테스트부터 시작해보겠다.
아무 클래스를 생성 해보자.

public class JUnitTest {
    @Test
    public void Test() {
        String str = "hi Junit";
        
        assertThat(str, is("hi Junit"));
    }
}
cs

Test() 함수하나를 만든뒤 (함수이름은 아무거나 상관없다.
String 형인 str 변수의 값이 "hi Junit"인지 테스트 해볼 것이다.
그러기 위해서는 Junit에서 제공해주는 assertThat 스태틱함수를 사용할 것이다.

코드설명

public static <T> void assertThat(T actual, Matcher<? super T> matcher) 

assertThat 함수는 두번째 파라미터인 matcher와 조건이 일치하는지 확인한다.
만약 일치하지 않는다면 2번째 변수의 값과 함께 AssertionError Exception이 발생하게 된다.

(Matcher 인터페이스 API를 찾아보면 Matcher는 Matcher 자체로 구현하지 말고 대신에
추상클래스인 BaseMatcher를 상속받으라고 되어 있다. 
일반적인 Matcher 구현을 쉽게 액세스 하려면 CoreMatchers의 정적팩터리메서드를 사용하라고
나와 있다.)
2번째 변수는 Matcher 타입과 같이 사용해야 하는데 보통 CoreMatchers에 있는 


public class CoreMatchers {
 public static <T> org.hamcrest.Matcher<T> is(org.hamcrest.Matcher<T> matcher) {
     return org.hamcrest.core.Is.<T>is(matcher);
}
cs

첫번 째 값이 is( " 이 값과 같은지 " ) 로 자주 쓰인다.


테스트 성공시 초록불이 뜬다


CoreMatches에 관한 메서드들

- allOf(Iterable<Matcher<? super T>> matchers) : 선언된 모든 매처가 전부 맞으면 통과한다.
- any(Class<T> type) : type의 오브젝트와 일치할 때 통과한다.
- anyOf(Iterable<Matcher<? super T>> matchers)  : 선언된 객체가 하나라도 일치하는 경우 통과한다.
- anything() : 선언된 객체에 상관없이 모든지 일치한다.
- both(Matcher<? super LHS> matcher) : 선언된 객체가 둘다 일치할 경우 통과한다.
- containsString(String substring) : 선언해준 문자를 포함하는 경우 통과한다.
- either(Matcher<? super LHS> matcher) : 선언된 매처중 둘중에 하나라도 일치하면 통과한다.
- endsWith(String suffix) : 문자열이 선언된 문자열로 끝나는 경우 통과한다.
- equalTo(T operand) : equals 메소드처럼 객체는 다르나 논리적으로 같을 때 통과한다.
assertThat("hi",equalTo("hi"));
cs
- hasItem(Matcher<? super T> itemMatcher) : 배열중에 하나라도 해당 값이 있을 때 통과한다.
- hasItems(Matcher<? super T>... itemMatchers) : 배열중 선언된 값이 모두 있을 때 통과한다.
- instanceOf(Class<?> type) : 선언된 객체가 같은 객체일 때 통과한다.
- is(T value) : 주로 equlaTo()처럼 논리적으로 같은지 확인한다.
is(Matcher<T> matcher) : 다른 매처를 꾸며줌, 용도에는 지장주지 않고 좀더 향샹된 표현식을 제공.

assertThat("hi",is("hi"));
cs
- not(Matcher<T> matcher) : 매처의 결과를 뒤집는다.
- not(T value) : not(equalTo(x))로 짧게 쓰는 단축어
- notNullValue()  : not(nullValue())를 짧게쓰는 단축어
- notNullValue(Class<T> type)  : not(nullValue(X.class))를 짧게쓰는 단축어
- sameInstance(T target) : 선언된 객체가 같은 인스턴스면 통과한다.
- startsWith(String prefix) : String이 선언된 객체로 시작하면 통과한다.
- theInstance(T target) : 선언된 객체가 같은 인스턴스면 통과 한다.


어노테이션 

- @Test 
가장 자주쓰이는 어노테이션으로 public void로 쓰여진 함수 위에 적어주면 JUnit에게 이건 test할 함수라도 알려주는 것이다.

- @Before
테스트 하기전에 미리 만들어져야 할 오브젝트들이 만들어져야 할 함수에게 써준다.

-@BeforeClass
몇몇 테스트 작업들은 (예를 들면 DB 로깅 작업들)은 많은 자원을 필요로 하는데 이때 사용하는 어노테이션

- @After
테스트가 끝나고 할 작업이 적힌 함수에게 붙여준다. 주로 테스트가 끝나고 자원 해제 등 마무리 작업을 해주어야할 때 사용하는 어노테이션이다.

- @AfterClass
모든 테스트가 끝나고 실행될 클래스 ( 예를 들면 BeforeClass에 적어논 것들을 해제해준다든지) 같은 작업을 해주는 어노테이션

- @Ignore
가끔 test를 하고싶지 않는 메소드에 붙여주면 그걸 제외하고 테스트하게 된다. 


DI설정파일 불러오기

- @RunWith(SpringJUnit4ClassRunner.class)

이 어노테이션을 클래스위에 붙여주게되면 내장된 Runner 클래스 대신 해당 클래스를 테스트 하기 위한 다른 클래스를 불러온다.

- @ContextConfiguration 

설정 파일이름을 지정하지 않으면 클래스이름 + "-comtext.xml" 이 디폴트로 사용된다.
(반드시 같은 폴더내에 있어야 한다.)
다른 이름의 xml 파일을 사용하고 싶다면
@ContextConfiguration(locations = "/test-applicationContext.xml")
을 사용하면 된다.
@RunWith 어노테이션이랑 같이 쓸것.


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "/test-applicationContext.xml")
//@ContextConfiguration
public class UserDaoTest {
    
}
cs


JUnit의 장점중 하나는 @Test 함수 하나하나 단일 객체로 다른 Test에는 영향을 안준다는 것이다.


public class JUnitTest {
    
    Math math;
    @Before
    public void setUp() {
        math = new Math();
    }
    
    @Test
    public void test() {
        System.out.println(math.hashCode());    
    }
    
    @Test
    public void test2() {
        System.out.println(math.hashCode());
    }
}
cs
같은 해시코드가 아니므로 객체가 두개 생기는걸 알 수 있다.








 setUp() -> test() -> test 끝 -> SetUp() -> test2() -> test2 끝 
이렇게 계속 된다.

코드를 짤때 반드시 테스트 지향적인 코드를 짠다면 
유지보수에서 굉장히 좋다. 한번만 run해보면 정상코드인지 바로 알수있기 떄문.











댓글

댓글 쓰기

이 블로그의 인기 게시물

Filter url 제외시키기

[Spring,Java] Validator 구현하기

[Spring] Mock framework에 대하여