AssertJ๋?
โญ๏ธ ํ
์คํธ์ ๊ด๋ จ๋ ๋ง์ ๊ธฐ๋ฅ์ ์ ๊ณตํ๊ณ ๋ฉ์๋ ์ฒด์ด๋์ผ๋ก ๊ฐ๋
์ฑ ๋์ ํ
์คํธ ์ฝ๋ ์์ฑ์ ์ง์ํ๋ ์คํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์
๋๋ค.
โญ๏ธ assertThat(๊ฒ์ฆ๋์)๋ก ์์ํ๋ฉฐ ๋ฉ์๋ ์ฒด์ด๋์ ์ด์ฉํ์ฌ ๊ฒ์ฆ ๋ฉ์๋๋ฅผ ์ฐ์์ ์ผ๋ก ๋ ๊น๋ํ๊ณ ๊ฐ๋
์ฑ ์๊ฒ ํ
์คํธ ์ฝ๋๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
ํ์ต ํ๊ฒฝ
plugins {
id 'org.springframework.boot' version '2.7.2'
id 'io.spring.dependency-management' version '1.0.12.RELEASE'
id 'java'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.bo ot:spring-boot-starter-test'
}
tasks.named('test') {
useJUnitPlatform()
}
1. Test Fail Message
@Test
public void test1() {
String str = "๊ฐ์";
assertThat(str).as("๊ธฐ๋๊ฐ {๋ฐ์}์ ํ์ฌ๊ฐ {%s}๊ฐ ์ผ์นํ์ง ์์ต๋๋ค.", str)
.isEqualTo("๋ฐ์");
}
โญ๏ธ as(String description, Object... args)๋ฅผ ์ฌ์ฉํ์ฌ ํ
์คํธ ์ฝ๋์ ์คํจ ๋ฉ์์ง๋ฅผ ์ค์ ํ ์ ์์ต๋๋ค.
โญ๏ธ as๋ ๊ฒ์ฆ ๋ฌธ๋ณด๋ค ์์ ์์ฑํด์ผ ํ๋ฉฐ, ๊ทธ๋ ์ง ์์ ๊ฒฝ์ฐ ๊ฒ์ฆ ๋ฌธ ์ดํ ํธ์ถ์ด ์ค๋จ๋จ์ผ๋ก ๋ฌด์๋ฉ๋๋ค.
2. Collection Filtering๊ณผ Assertions
import org.assertj.core.util.Lists;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.not;
import static org.assertj.core.api.AssertionsForClassTypes.in;
import static org.assertj.core.api.AssertionsForClassTypes.notIn;
@SpringBootTest
class MemberTest {
public Member member1, member2, member3;
public List<Member> members;
@BeforeEach
public void createMember() {
member1 = new Member("Kim", 20, MemberRole.ADMIN);
member2 = new Member("Ahn", 20, MemberRole.BASIC);
member3 = new Member("Park", 21, MemberRole.VIP);
members = Lists.list(member1, member2, member3);
}
/**
* ๋ฆฌ์คํธ ์ค ๋์ด๊ฐ 20์ด์ธ ๋ฉค๋ฒ๋ค์ member1๊ณผ member2๋ง์ด ์ ์ผํ๋ค.
*/
@Test
public void test1() {
assertThat(members)
.filteredOn("age", 20)
.containsOnly(member1, member2);
}
/**
* ๋ฆฌ์คํธ ์ค ๋์ด 19,20๋ฅผ ํฌํจํ์ง ์์ ๋ฉค๋ฒ๋ member3์ด ์ ์ผํ๋ค.
*/
@Test
public void test2() {
assertThat(members)
.filteredOn("age", notIn(19, 20))
.containsOnly(member3);
}
/**
* ๋ฆฌ์คํธ ์ค ๋์ด๊ฐ 20์ธ ์ฌ๋์ member1๊ณผ member2๊ฐ ์ ์ผํ๋ค.
*/
@Test
public void test3() {
assertThat(members)
.filteredOn("age", in(20))
.containsOnly(member1, member2);
}
/**
* ๋ฆฌ์คํธ ์ค ์ด๋ฆ์ด Lee๊ฐ ์๋ ๋ฉค๋ฒ๋ค์ member1, member2, member3์ด ์ ์ผํ๋ค.
*/
@Test
public void test4() {
assertThat(members)
.filteredOn("name", not("Lee"))
.containsOnly(member1, member2, member3);
}
/**
* ์ฒด์ด๋์ผ๋ก ํํฐ๋ง์ ์ด์ด๊ฐ ์๋ ์๋ค.
*/
@Test
public void test5() {
assertThat(members)
.filteredOn("age", 21)
.filteredOn("name", not("Park"))
.isEmpty();
}
/**
* ๋๋ค์์ผ๋ก ์กฐ๊ฑด๋ ์ค ์ ์๋ค.
*/
@Test
public void test6() {
assertThat(members)
.filteredOn("age", 20)
.filteredOn(member -> member.age > 20)
.isEmpty();
}
}
3. Collection Data Extracting
/**
* members์ name์ ํ
์คํธํ ๋ ์๋์ ๊ฐ์ ๋ฒ๊ฑฐ๋ก์ด ๋ฐฉ์์ผ๋ก ํ
์คํธ ํ ์ ์๋ค.
*/
@Test
public void test7() {
List<String> names = new ArrayList<>();
for (Member member : members) {
names.add(member.getName());
}
assertThat(names).containsOnly("Kim", "Ahn", "Park");
}
/**
* ํ
์คํธ 7๋ฒ์ ๊ฐ์ ํ ์ฝ๋
* extracting์ ์ฌ์ฉํ๋ฉด ๊ฐ๊ฒฐํ๊ฒ ํ
์คํธํ ์ ์๋ค.
*/
@Test
public void test8() {
assertThat(members)
.extracting("name")
.containsOnly("Kim", "Ahn", "Park");
}
/**
* members์ member ์ด๋ฆ๋ค์ Kim๊ณผ Ahn์ ํฌํจํ๊ณ Lee๋ ํฌํจํ์ง ์๋๋ค.
*/
@Test
public void test8_1() {
assertThat(members)
.extracting("name")
.contains("Kim", "Ahn")
.doesNotContain("Lee");
}
4. Soft Assertions
โญ๏ธ ๋ณดํต ํ ์คํธ๋ฅผ ์งํํ ๋ ์์ ๊ฒ์ฆ์ด ์คํจํ๋ฉด ํด๋น ํ ์คํธ๋ ์ ๋ถ ์ค์ง๋ฉ๋๋ค.
@SpringBootTest
class MemberTest {
public Member member1, member2, member3;
public List<Member> members;
@BeforeEach
public void createMember() {
member1 = new Member("Kim", 20, MemberRole.ADMIN);
member2 = new Member("Ahn", 20, MemberRole.BASIC);
member3 = new Member("Park", 21, MemberRole.VIP);
members = Lists.list(member1, member2, member3);
}
/**
* ์ฒซ ๋ฒ์งธ assert์์ ์คํจํ์ฌ ๋ค์ assert๋ ์ํํ์ง ์๋๋ค.
*/
@Test
public void noSoftAssertionTest() {
assertThat(members).as("ํฌ๊ธฐ๊ฐ ์ผ์นํ์ง ์์ต๋๋ค.").size().isEqualTo(1);
assertThat(members).as("์ ๊ฒ์ฆ์์ ๋ฉ์ถฐ ์ฌ๊ธฐ๊น์ง ์ค์ง ์์ต๋๋ค.").size().isEqualTo(2);
}
}
์ ์ฝ๋๋ ์ฒซ ๋ฒ์งธ assert์์ ์คํจํ์ฌ ์๋์ ๋ ๋ฒ์งธ assert๋ ์ํํ์ง ์์ต๋๋ค.
โญ๏ธ ์๋์ ๊ฐ์ด Soft Assertions์ ์ด์ฉํ๋ฉด ์ด์ ์ ์คํจ์ ์๊ด์์ด ๋ชจ๋ asserThat๋ฅผ ์คํํ ๋ค ์คํจ ๋ด์ญ์ ์ ๋ถ ํ์ธํ ์ ์์ต๋๋ค.
@SpringBootTest
class MemberTest {
public Member member1, member2, member3;
public List<Member> members;
@BeforeEach
public void createMember() {
member1 = new Member("Kim", 20, MemberRole.ADMIN);
member2 = new Member("Ahn", 20, MemberRole.BASIC);
member3 = new Member("Park", 21, MemberRole.VIP);
members = Lists.list(member1, member2, member3);
}
/**
* ์ฒซ ๋ฒ์งธ assert๊ฐ ์คํจํ๋๋ผ๋ ๋ชจ๋ assert๋ฅผ ์ํํ๋ค.
*/
@Test
public void softAssertionTest() {
SoftAssertions softAssertions = new SoftAssertions();
softAssertions.assertThat(members).as("ํฌ๊ธฐ๊ฐ ์ผ์นํ์ง ์์ต๋๋ค.").size().isEqualTo(1);
softAssertions.assertThat(members).as("์ ๊ฒ์ฆ์์ ์คํจํ๋๋ผ๋ ๋ชจ๋ assert๋ฅผ ์ํํฉ๋๋ค.").size().isEqualTo(2);
softAssertions.assertAll(); // assertAll()์ ํตํด ์คํํฉ๋๋ค.
}
}
โญ๏ธ ์๋์ ๊ฐ์ด assertSoftly๋ฅผ ์ฌ์ฉํด ๋๋ค์์ผ๋ก ๋ฐ๋ก assertAll์ ํธ์ถํ ํ์ ์์ด ์ฌ์ฉํ ์๋ ์์ต๋๋ค.
@SpringBootTest
class MemberTest {
public Member member1, member2, member3;
public List<Member> members;
@BeforeEach
public void createMember() {
member1 = new Member("Kim", 20, MemberRole.ADMIN);
member2 = new Member("Ahn", 20, MemberRole.BASIC);
member3 = new Member("Park", 21, MemberRole.VIP);
members = Lists.list(member1, member2, member3);
}
/**
* assertSoftly๋ฅผ ์ฌ์ฉํด ๋๋ค์์ผ๋ก ๋ฐ๋ก assertAll์ ํธ์ถํ ํ์ ์์ด ์ฌ์ฉํ ์ ์๋ค.
*/
@Test
public void softAssertionTest_2() {
SoftAssertions.assertSoftly(softAssertions -> {
softAssertions.assertThat(members).as("ํฌ๊ธฐ๊ฐ ์ผ์นํ์ง ์์ต๋๋ค.").size().isEqualTo(1);
softAssertions.assertThat(members).as("์ ๊ฒ์ฆ์์ ์คํจํ๋๋ผ๋ ๋ชจ๋ assert๋ฅผ ์ํํฉ๋๋ค.").size().isEqualTo(2);
});
}
}
5. Exception Assertions
โญ๏ธ ์์ธ๊ฐ ๋ฐ์ํ๋ค๊ณ ๊ฐ์ ํ๊ณ , ์์ํ ์์ธ์ธ์ง ๊ฒ์ฆํ๋ ๋ฐฉ๋ฒ์ ์๋์ ๊ฐ์ต๋๋ค.
Java 8์์ Assertion์ ํ ์คํธํ๋ ๊ฒ์ ํธ๋ฆฌํ๋ฐ, assertThatThrownBy(ThrowingCallable)๋ฅผ ์ฌ์ฉํ๋ฉด ์๋์ ๊ฐ์ด ๊ฐ๋ ์ฑ ์๊ณ ํธ๋ฆฌํ๊ฒ ์์ธ๋ฅผ ๋์ง๊ณ ๊ฒ์ฆํ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
/**
* ์์ธ ๋ฐ์!์ด๋ผ๋ ์์ธ๋ฅผ ๋์ง๊ณ , hasMessageContaining์์ ํด๋น ์์ธ ๋ฉ์์ง์ ์ผ์นํ์ง ๊ฒ์ฆํ๋ค.
*/
@Test
public void testException_01() {
assertThatThrownBy(() -> {
throw new Exception("์์ธ ๋ฐ์!");
})
.isInstanceOf(Exception.class)
.hasMessageContaining("์์ธ ๋ฐ์!");
}
โญ๏ธ AssertJ์์๋ ์์ฃผ ๋ฐ์ํ๋ ์์ธ๋ค์ ๋ํด์ ์ ์๋ ํจ์๋ฅผ ์ ๊ณตํ๋ฉฐ. ๋ํ์ ์ผ๋ก 4๊ฐ์ง๊ฐ ์์ต๋๋ค.
1. assertThatNullPointerException
2. assertThatIllegalArgumentException
3. assertThatIllegalStateException
4. assertThatIOException
โญ๏ธ ๋ง์ฝ ์์ ๋ํ์ ์ธ ๋ค ๊ฐ์ง ์์ธ๋ฅผ ์ฌ์ฉํ๋ค๋ฉด ์๋์ ๊ฐ์ด ์์ฑํ ์ ์์ต๋๋ค.
/**
* ๋ํ์ ์ธ 4๊ฐ์ง ์์ธ์ ํฌํจ ๋์๋ค๋ฉด ์๋์ ๊ฐ์ด ์์ฑํ ์ ์๋ค.
*/
@Test
public void testException_02() {
assertThatIOException().isThrownBy(() -> {
throw new IOException("์์ธ ๋ฐ์!");
})
.withMessage("%s!", "์์ธ ๋ฐ์!")
.withMessageContaining("์์ธ ๋ฐ์!")
.withNoCause();
}
โญ๏ธ ๋ง์ฝ ์ ๋ค ๊ฐ์ง ์์ธ์ ํฌํจ๋์ง ์์๋ค๋ฉด ์๋์ ๊ฐ์ด ์์ฑํ๋ฉด ๋ฉ๋๋ค.
/**
* ๋ํ์ ์ธ 4๊ฐ์ง ์์ธ์ ํฌํจ๋์ง ์์๋ค๋ฉด ์๋์ ๊ฐ์ด ์์ฑํ๋ฉด ๋๋ค.
*/
@Test
public void testException_03() {
assertThatExceptionOfType(IOException.class)
.isThrownBy(() -> {
throw new IOException("์์ธ ๋ฐ์!");
})
.withMessage("%s", "์์ธ ๋ฐ์!")
.withMessageContaining("์์ธ ๋ฐ์!")
.withNoCause();
}
โญ๏ธ BDD(ํ๋ ์ฃผ๋ ๊ฐ๋ฐ) ๋ฐฉ์์ผ๋ก๋ ์๋์ ๊ฐ์ด ์์ฑํ ์ ์์ต๋๋ค.
/**
* BDD(ํ๋ ์ฃผ๋ ๊ฐ๋ฐ) ๋ฐฉ์์ผ๋ก ์์ฑํ๋ฉด ์๋์ ๊ฐ๋ค.
*/
@Test
public void testException_04() {
//given
//when
Throwable thrown = catchThrowable(() -> {
throw new Exception("์์ธ ๋์ง๊ธฐ!");
});
//then
assertThat(thrown)
.isInstanceOf(Exception.class)
.hasMessageContaining("์์ธ ๋์ง๊ธฐ!");
}
์ฐธ๊ณ
- https://joel-costigliola.github.io/assertj/assertj-core-features-highlight.html
- https://sun-22.tistory.com/86
ํ ์คํธ ๊ด๋ จ ๊ฐ์ด ๋ณด๋ฉด ์ข์ ๊ธ
'BackEnd๐ฑ > Spring' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Actuator dependency and Swagger Stater 3.0.0 ์ถฉ๋ ์๋ฌ (0) | 2022.11.11 |
---|---|
JUnit5 ์์ธํ ์์๋ณด๊ธฐ (3) | 2022.10.02 |
[Spring] StringUtils ์ ์ฉํ ๋ฉ์๋ ์ ๋ฆฌ (0) | 2022.08.31 |
[Querydsl] unable to load class com.mysema.codegen.model.type'. error (1) | 2022.07.31 |
[Spring] [BaseTimeEntity, JPA Auditing]์ ํตํ ์์ฑ์๊ฐ/์์ ์๊ฐ ์๋ํ (1) | 2022.05.22 |
[Spring] @Valid, @ControllerAdvice, @Exception์ ์ด์ฉํ ๋ฐ์ดํฐ ๊ฒ์ฆ ๋ฐ ์ฒ๋ฆฌ (0) | 2022.05.20 |
๋๊ธ