테스팅(Testing)_Hamcrest

김예인·2023년 7월 4일

백엔드 공부일지

목록 보기
41/43
post-thumbnail

Hamcrest

JUnit 기반의 단위 테스트에서 사용할 수 있는 Assertion Framework

  • Assertion을 위한 매쳐(Matcher)가 자연스러운 문장으로 이어져 가독성 향상
  • 이해하기 쉬운 테스트 실패 메시지
  • 다양한 Matcher 제공

JUnit Assertion을 사용한 단위 테스트에 Hamcrest Assertion 적용하기

💻 예시1 : Assertion 코드의 가독성 향상

<JUnit에서의 Assertion>

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class HelloJunitTest {

    @DisplayName("Hello Junit Test")
    @Test
    public void assertionTest1() {
        String actual = "Hello, JUnit";
        String expected = "Hello, JUnit";

		// Assertion
        // assertEquals() : 동일한 값인지 비교
        assertEquals(expected, actual); 
    }
}

<Hamcrest에서의 Assertion>

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;

public class HelloHamcrestTest {

    @DisplayName("Hello Junit Test using hamcrest")
    @Test
    public void assertionTest1() {
        String expected = "Hello, JUnit";
        String actual = "Hello, JUnit";

		// Assertion
        // is(), equalTo() Matcher 사용
        assertThat(actual, is(equalTo(expected)));
    }
}

💻 예시2 : 실행 결과 'faild' 메시지의 가독성 향상

<JUnit에서의 Assertion>

package com.codestates.basic;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;

public class HelloJunitTest {

    @DisplayName("Hello Junit Test")
    @Test
    public void assertionTest1() {
        String actual = "Hello, JUnit";
        String expected = "Hello, World";

        assertEquals(expected, actual); // faild
    }
}

<실행 결과 메시지>

expected: <Hello, World> but was: <Hello, JUnit>
Expected :Hello, World
Actual   :Hello, JUnit

<Hamcrest에서의 Assertion>

package com.codestates.hemcrest;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;

public class HelloHamcrestTest {

    @DisplayName("Hello Junit Test using hamcrest")
    @Test
    public void assertionTest() {
        String expected = "Hello, World";
        String actual = "Hello, JUnit";

        assertThat(actual, is(equalTo(expected))); // faild
    }
}

<실행 결과 메시지>

Expected: is "Hello, World"
     but: was "Hello, JUnit"

💻 예시3 : Assertion 코드와 실패메시지 가독성 향상

<테스트 대상 클래스>

package com.codestates;

import java.util.HashMap;
import java.util.Map;

public class CryptoCurrency {
    public static Map<String, String> map = new HashMap<>();

    static {
        map.put("BTC", "Bitcoin");
        map.put("ETH", "Ethereum");
        map.put("ADA", "ADA");
        map.put("POT", "Polkadot");
    }
}

<JUnit에서의 Assertion>

package com.codestates.basic;

import com.codestates.CryptoCurrency;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertNotNull;

public class AssertionNullHamcrestTest {

    @DisplayName("AssertionNull() Test")
    @Test
    public void assertNotNullTest() {
        String currencyName = getCryptoCurrency("ETH");

		// JUnit의 Not Null 테스트 Assertion
        assertNotNull(currencyName, "should be not null");
    }

    private String getCryptoCurrency(String unit) {
        return CryptoCurrency.map.get(unit);
    }
}

<Hamcrest에서의 Assertion>

package com.codestates.hemcrest;

import com.codestates.CryptoCurrency;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;

public class AssertionNullHamcrestTest {

    @DisplayName("AssertionNull() Test")
    @Test
    public void assertNotNullTest() {
        String currencyName = getCryptoCurrency("ETH");

		// Hamcrest의 `is()`, `notNullValue()` 매쳐
        assertThat(currencyName, is(notNullValue()));   // (1)
//      assertThat(currencyName, is(nullValue()));      // (2)
    }

    private String getCryptoCurrency(String unit) {
        return CryptoCurrency.map.get(unit);
    }
}

💻 예시4 : JUnit 과 Hamcrest 혼합

<JUnit에서의 Assertion>

package com.codestates.basic;

import com.codestates.CryptoCurrency;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

public class AssertionExceptionTest {

    @DisplayName("throws NullPointerException when map.get()")
    @Test
    public void assertionThrowExceptionTest() {
    
    	// asserThrows() : 예외발생 여부 테스트
        assertThrows(NullPointerException.class, () -> getCryptoCurrency("XRP"));
    }

		...
		...

    private String getCryptoCurrency(String unit) {
        return CryptoCurrency.map.get(unit).toUpperCase();
    }
}

<Hamcrest에서의 Assertion>

package com.codestates.hemcrest;

import com.codestates.CryptoCurrency;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertThrows;

public class AssertionExceptionHamcrestTest {

    @DisplayName("throws NullPointerException when map.get()")
    @Test
    public void assertionThrowExceptionTest() {
    
    	// JUnit : assertThrows() 메서드
        Throwable actualException = assertThrows(NullPointerException.class,
                () -> getCryptoCurrency("XRP")); // passed

		// Hamcrest : throw 된 Exception 타입이 기대했던 Exception 타입과 일치하는지 추가로 검증
        assertThat(actualException.getClass(), is(NullPointerException.class)); // passed
    }

    private String getCryptoCurrency(String unit) {
        return CryptoCurrency.map.get(unit).toUpperCase();
    }
}
profile
백엔드 개발자 김예인입니다.

0개의 댓글