> For the complete documentation index, see [llms.txt](https://docs.sysout.co.kr/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.sysout.co.kr/web/back-end/what-is-spring-framework/spring-test/assert.md).

# Assert 단정문

## 단정문

두 번째 테스트케이스를 생성한다.

> com.hakademy.spring11.Test02

```java
package com.hakademy.spring11;

import org.junit.Test;

public class Test02 {
	@Test
	public void calculate() {
		int a = 10;
		int b = 20;
		int c = 30;
		
		System.out.println(a + b == c);
	}
}
```

이 테스트케이스는 a와 b의 합계가 c와 같다는 것을 테스트하기 위해 작성했다.\
이 테스트케이스를 실행하면 다음과 같은 결과가 나온다.

![](/files/-MdFhO2gAK6-tKIVpXdL)

콘솔에 출력되는 값은 `true`이며 테스트케이스가 성공했음을 알 수 있다.

위의 테스트케이스에서 c의 값을 수정하여 29로 변경해본다.

```java
package com.hakademy.spring11;

import org.junit.Test;

public class Test02 {
	@Test
	public void calculate() {
		int a = 10;
		int b = 20;
		int c = 29;
		
		System.out.println(a + b == c);
	}
}
```

테스트 실행 결과는 다음과 같다.

![](/files/-MdFhRAiDSDbriWpj_Q4)

a+b와 c가 같지 않으므로 콘솔에 `false`가 나오지만 테스트는 여전히 성공으로 나오고 있다.

a+b와 c가 같으리라고 기대했을 수도 있고, 같지 않으리라 기대했을 수도 있겠지만 어떠한 상황을 기대했던 성공/실패 여부를 확인하기가 쉽지 않다.

즉, 내가 원하는 상황이 나오면 성공, 내가 원하지 않는 상황이 나오면 실패로 처리할 수 있어야 하며 이럴 때 JUnit에서 제공하는 단정문을 사용하면 쉽게 처리가 가능하다.

> com.hakademy.spring11.Test03

```java
package com.hakademy.spring11;

import org.junit.Test;
import junit.framework.Assert;

public class Test03 {
	@Test
	public void calculate() {
		int a = 10;
		int b = 20;
		int c = 30;
		
		Assert.assertEquals(a + b, c);
	}
}
```

실행하면 다음과 같이 성공 화면이 나온다.

![](/files/-MdFhXKduhVDhkysYqob)

값을 변경하여 실행해보면 다른 결과가 나온다는 것을 알 수 있다.

```java
package com.hakademy.spring11;

import org.junit.Test;
import junit.framework.Assert;

public class Test03 {
	@Test
	public void calculate() {
		int a = 10;
		int b = 20;
		int c = 29;
		
		Assert.assertEquals(a + b, c);
	}
}
```

![](/files/-MdFhVcw_2LNIgkueter)

결과가 실패로 나오기 때문에 내가 원하는 상황이 나오지 않았음을 알 수 있다.

이렇게 단정문을 사용하면 테스트 결과를 조금 더 이해하기 쉽게 만들 수 있다.

`Assert.assertEquals(a + b, c);` 의 형태로 사용할 경우 Deprecated 표시가 나오는데 테스트케이스에서는 JUnit 관련 기능들을 좀 더 쉽게 쓸 수 있도록 static import를 권장하고 있다.

```java
import static org.junit.Assert.assertEquals;
```

```java
assertEquals(a + b, c);
```

자동완성을 이용하면 조금 더 쉽게 구문을 완성할 수 있다.

## 단정문의 종류

JUnit의 단정문 종류는 다음과 같다.

### **assertEquals**

assertEquals는 두 객체가 동등함을 단정하기 위한 구문이다.

```java
assertEquals([메시지], 기대값 , 실제값)
```

메시지의 경우 실패시 표시될 내용이며 생략이 가능하다.

> 주의 : "동일"이 아닌 "동등"이기 때문에 자바의 equals와 같은 형태이다.

### **assertNotEquals**

assertEquals의 반대인 두 객체가 동등하지 않음을 단정하기 위한 구문이다.

```
assertNotEquals([메시지], 기대값, 실제값)
```

### **assertArrayEquals**

assertArrayEquals는 두 배열이 동등함을 단정하기 위한 구문이다.

```
assertArraysEquals([메시지], 기대배열, 실제배열)
```

**assertSame**

assertSame은 두 객체가 동일함을 단정하기 위한 구문이다.

```
assertSame([메시지], 기대값, 실제값)
```

> 주의 : assertSame은 "동일" 비교이기 때문에 == 와 같은 형태이다.

### **assertNotSame**

assertSame의 반대인 두 객체가 동일하지 않음을 단정하기 위한 구문이다.

```
assertNotSame([메시지], 기대값, 실제값)
```

### **assertNull**

assertNull은 대상 객체가 null임을 단정하기 위한 구문이다.

```
assertNull([메시지], 객체)
```

### **assertNotNull**

assertNull과 반대로 대상 객체가 null이 아님을 단정하기 위한 구문이다.

```
assertNotNull([메시지], 객체)
```

### **assertTrue**

assertTrue는 해당 결과가 true임을 단정하기 위한 구문이다.

```
assertTrue([메시지], 값)
```

일반적으로 값 자리에 논리식을 작성하여 검증한다.

### **assertFalse**

assertFalse는 해당 결과가 false임을 단정하기 위한 구문이다.

```
assertFalse([메시지], 값)
```

일반적으로 값 자리에 논리식을 작성하여 검증한다.

### **assertThat**

assertThat은 다양한 상황을 단정하기 위한 구문이다.

```
assertThat([메시지], 실제값, Matcher)
```

Matcher란 다양한 상황을 검증하기 위해 제공되는 명령 집합을 의미한다.

JUnit에서는 다양한 Matcher를 지원한다.

예를 들어 다음 구문은 같은 상황을 단정한다.

```java
assertTrue(10 + 20 == 30);
assertEquals(30, 10 + 20);
assertThat(10 + 20, is(30));
```

위의 구문에서 is()가 Matcher이며, 이와 같은 Matcher들은 다음 종류들이 존재한다.

* allOf : 내부에 선언된 모든 Matcher가 정상일 경우 통과
* anyOf : 내부에 선언된 Mathcer중 1개 이상 정상일 경우 통과
* both : and로 연결된 두 Matcher가 모두 정상일 경우 통과
* either : or로 연결된 두 Matcher중 1개
* everyItem : 배열 or 리스트 요소를 순회하며 검사하여 모두 정상일 경우 통과
* is : 비교하거나, 다른 Matcher와 조합할 때 사용
* isA : 타입 검사를 수행하여 정상일 경우 통과
* anything : 항상 통과
* hasItem : 배열에서 Matcher에서 요구하는 값이 1개 이상일 경우 통과
* hasItems : 배열에서 Matcher에서 요구하는 값들이 모두 1개 이상 있을 경우 통과
* equalsTo : 값을 비교하여 같을 경우 통과
* not : 단독으로 사용할 경우 같지 않음을 검사, is와 결합하여 부정할 때도 사용
* nullValue : 비교값이 null일 경우 통과
* notNullValue : 비교값이 null이 아닐 경우 통과
* sameInstance : 비교값이 동일한 인스턴스일 경우 통과
* theInstance : sameInstance와 동일
* containsString : 대상에 특정 문자열이 포함되어 있을 경우 통과
* startsWith : 대상이 특정 문자열로 시작할 경우 통과
* endsWith : 대상이 특정 문자열로 종료할 경우 통과
* 직접 정의 : 내가 원하는 검사 방식을 직접 구현

## 작성 예시

```java
package com.hakademy.spring11;

import static org.hamcrest.CoreMatchers.everyItem;
import static org.hamcrest.CoreMatchers.hasItem;
import static org.hamcrest.CoreMatchers.hasItems;
import static org.junit.Assert.assertThat;

import java.util.Arrays;
import java.util.List;

import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;
import org.junit.Test;

/**
 * AssertThat 다루기
 * @author Hakademy
 */
public class Test04 {

	@Test
	public void test() {
		int a = 10, b = 20, c = 30;
		
//		1. a + b가 c와 같다고 단정
//		assertThat(a + b, is(c));
		
//		2. a + b가 int 형태라고 단정
//		assertThat(a + b, isA(int.class));
		
//		3. 1과 2를 모두 만족한다고 단정
//		assertThat(a + b, allOf(is(c), isA(int.class)));
		
//		4. 1과 2중 1개 이상 만족한다고 단정
//		assertThat(a + b, anyOf(is(c), isA(int.class)));
		
//		5. 1과 2를 모두 만족한다고 단정
//		assertThat(a + b, both(is(c)).and(isA(int.class)));
		
//		6. 1과 2중 1개 이상 만족한다고 단정
//		assertThat(a + b, either(is(c)).or(isA(int.class)));
		
//		7. a + b가 c와 같지 않다고 단정
//		assertThat(a + b, is(not(c)));
		
//		8. a + b가 null이라고 단정
//		assertNull(a + b);
//		assertThat(a + b, is(nullValue()));
		
//		9. a + b가 not null이라고 단정
//		assertNotNull(a + b);
//		assertThat(a + b, is(notNullValue()));
		
		String str = "junit test framework";
//		10. str에 "frame"이 있다고 단정
//		assertThat(str, containsString("frame"));
		
//		11. str이 "junit"으로 시작한다고 단정
//		assertThat(str, startsWith("junit"));
		
//		12. str이 "work"로 종료한다고 단정
//		assertThat(str, endsWith("work"));
		
//		13. 직접 정의한 Matcher 사용하기
//		a + b가 짝수라고 단정
//		assertThat(a + b, even());
		
		List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
//		14. list의 모든 구성요소가 int 형태라고 단정
//		assertThat(list, everyItem(isA(int.class)));
		
//		15. list의 모든 구성요소가 짝수라고 단정
//		assertThat(list, everyItem(even()));
		
//		16. list의 구성요소중 짝수가 존재한다고 단정
//		assertThat(list, hasItem(even()));
		
//		17. list의 구성요소 중 1, 3이 존재한다고 단정
//		assertThat(list, hasItems(1, 3));
		
//		18. list의 구성요소 중 5, 7이 존재한다고 단정
//		assertThat(list, hasItems(5, 7));
	}
	
//	사용자 정의 Matcher
	public Matcher<Integer> even(){
		return new TypeSafeMatcher<Integer>() {
			@Override
			public void describeTo(Description description) {
				description.appendText("짝수 검증");
			}
			@Override
			protected boolean matchesSafely(Integer item) {
				return item % 2 == 0;
			}
		};
	}
}
```
