hamcrest 로 가독성있는 jUnit Test Case 만들기

다양한 조건의 Match rule 을 손쉽게 작성하고 테스트 할 수 있는 library로 jUnit 이나 Mokoto 와 연계하여 사용할 수 있다.

예로 다음과 같은 jUnit assert 조건이 있다고 생각해 보자.

assertEquals(theBiscuit, myBiscuit); ;


이 구문은 아래와 같이 iseuqalTo 를 사용해서 더 가독성있게 바꿀수 있다.(3가지 모두 동일한 의미)

assertThat(theBiscuit, equalTo(myBiscuit)); 
assertThat(theBiscuit, is(equalTo(myBiscuit))); 
assertThat(theBiscuit, is(myBiscuit));


assert () 호출 조건이 헷갈렸다면 hamcrest 로 더 읽기 쉬운 테스트 코드를 작성할 수 있다.

설치

gradle

build.gradle 에 다음 구문을 추가한다.

dependencies {
    testImplementation 'org.hamcrest:hamcrest:2.2'
}


Maven Pom

<dependency>
    <groupId>org.hamcrest</groupId>
    <artifactId>hamcrest</artifactId>
    <version>2.2</version>
    <scope>test</scope>
</dependency>         


Matchers

기본적으로 다양한 Matcher 가 제공되며 중요한 Matcher들은 다음과 같다.

Core

  • anything - always matches, useful if you don't care what the object under test is
  • describedAs - decorator to adding custom failure description
  • is - decorator to improve readability - see "Sugar", below

Logical

  • allOf - matches if all matchers match, short circuits (like Java &&)
  • anyOf - matches if any matchers match, short circuits (like Java ||)
  • not - matches if the wrapped matcher doesn't match and vice versa
import static org.hamcrest.Matchers.anything;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertThat;
import static org.hamcrest.Matchers.is;

 
// null 을 기대하는데 null 이므로 성공
@Test
public void nullTest() {
	String str = null;
	assertThat(str,  is(nullValue()));
}
 
// notnull 을 기대하는데 null 이므로 실패
@Test
public void notNullTest() {
	String str = null;
	assertThat(str,  is(notNullValue()));
}
 
 
// 또는 not 을 사용해도 됨
String str = null;
assertThat(str,  not(notNullValue()));
assertThat(str,  not(nullValue()));

Objects

  • equalTo - test object equality using Object.equals

  • hasToString - test Object.toString
  • instanceOf, isCompatibleType - test type
  • notNullValue, nullValue - test for null
  • sameInstance - test object identity
import static org.hamcrest.Matchers.instanceOf;
 
@Test
public void instanceOfTest() {
	HashMap<String, String> map1 = new HashMap<String, String>();
 
    // instance 가 다르므로 실패
	assertThat(map1, instanceOf(String.class));
}


Numbers

  • closeTo - test floating point values are close to a given value
  • greaterThan, greaterThanOrEqualTo, lessThan, lessThanOrEqualTo - test ordering
import static org.hamcrest.Matchers.lessThan;
import static org.hamcrest.Matchers.lessThanOrEqualTo;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
 
assertThat(2,  greaterThan(1));
		
assertThat(1,  greaterThanOrEqualTo(1));
		
assertThat(0,  lessThan(1));
assertThat(0,  lessThanOrEqualTo(1));


Beans

  • hasProperty - test JavaBeans properties

property 에 대한 getter, setter 중 하나만 있으면 성공

import static org.hamcrest.Matchers.hasProperty;
import static org.junit.Assert.assertThat;


// hasProperty 용 
private String myProperty;
	
public void  setMyProperty(String property) {
	this.property = property;
}
 
// 위에 myProperty가 있으므로 성공
@Test
public void propertyTest() {
    assertThat(this, hasProperty("myProperty"));
}

Collections

  • array - test an array's elements against an array of matchers

  • hasEntry, hasKey, hasValue - test a map contains an entry, key or value

  • hasItem, hasItems - test a collection contains elements

  • hasItemInArray - test an array contains an element

참고: http://crunchify.com/how-to-use-hamcrest-assertthat-matchers-to-create-junit-testcases-in-java-complete-tutorial/

@Test
public void test() {
    Map<String, String> map1 = new HashMap<String, String>();
    map1.put("foo1", "bar1");
    map1.put("foo2", "bar2");

    assertThat(map1, IsMapContaining.hasKey("foo1"));
    assertThat(map1, IsMapContaining.hasEntry("foo1", "bar1"));
    assertThat(map1, IsMapContaining.hasValue("bar1"));
}


Text 

  • equalToIgnoringCase - test string equality ignoring case
  • equalToIgnoringWhiteSpace - test string equality ignoring differences in runs of whitespace
  • containsString, endsWith, startsWith - test string matching
import static org.hamcrest.Matchers.equalToIgnoringCase;
import static org.hamcrest.Matchers.equalToIgnoringWhiteSpace;
 
//성공
assertThat("Spring",  equalToIgnoringCase("spring"));
 
// 성공. 문자열 앞뒤의 공백만 무시하니 주의.
assertThat("Spring Framework 3.2",  equalToIgnoringWhiteSpace ("   Spring Framework 3.2  "));
 
// 성공
assertThat("Spring Framework 3.2", containsString("Framework"));


Ref