JUnit5μ μ₯λ¨μ
μ₯μ
- JUnit5λ JUnit4μ λ¬Έμ μ μ 보μνκ³ μλ‘μ΄ κΈ°λ₯μ μΆκ°νμ΅λλ€.
- ν μ€νΈ μΈμ€ν΄μ€ λΌμ΄νμ¬μ΄ν΄μ μ§μνκ³ , λμ ν μ€νΈλ₯Ό μ§μνλ©°, ν μ€νΈ νλΌλ―Έν°ν κΈ°λ₯λ μΆκ°λμμ΅λλ€.
- λν λͺ¨λνκ° κ°λ₯νμ¬ νμν λͺ¨λλ§ μ¬μ©ν μ μμ΅λλ€.
- λ¨μ
- JUnit5λ μμ§ λ§μ Java κ°λ°μλ€μ΄ μ΅μνμ§ μμ΅λλ€. λν IDE μ§μμ΄ JUnit4μ λΉν΄ λ―Έν‘ν κ²½μ°λ μμ΅λλ€.
- JUnit5κ° JUnit4μ λΉν΄ λ§μ μλ‘μ΄ κΈ°λ₯μ μ 곡νλ―λ‘ μ΅κ·Όμλ λ λ§μ΄ μ¬μ©λκ³ μμ΅λλ€.
- κ·Έλ¬λ μΌλΆ νλ‘μ νΈμμλ μμ§ JUnit4λ₯Ό κ³μ μ¬μ©νκ³ μμ΅λλ€.
μ£Όμ μ΄λ Έν μ΄μ μ 리
@ExtendWith()
JUnit 5μ μ΄λ Έν μ΄μ μΌλ‘, JUnit 4μ `@RunWith` μ λ체νλ€. `@RunWith` μμ Runner μ ꡬν체λ₯Ό μΈμλ‘ λ°μλ κ²μ²λΌ, μ¬κΈ°μλ Extension μΈν°νμ΄μ€μ ꡬν체λ₯Ό μΈμλ‘ λ°λλ€. Junit 5 Testμμ μ¬μ©ν κΈ°λ₯μ νμ₯ν λ μ¬μ©λλ€.
μ΄λ μ΅μ
μΌλ‘ `@ExtendWith (SpringExtension.class)`μ `@ExtendWith (MockitoExtension.class)`μ΄ λ§μ΄μ°μΈλ€.
@ExtendWith (SpringExtension.class) - Spring MVC ν μ€νΈ
SpringExtensionμ Spring ν μ€νΈλ₯Ό μ½κ²ν μ μλλ‘ λμμ£Όλ Extensionμ λλ€. μ΄λ₯Ό μ΄μ©νλ©΄ Spring ν μ€νΈμ μ¬μ©ν ApplicationContextλ₯Ό μ½κ² μμ±ν μ μμ΅λλ€.
(π SpringExtensionμ ApplicationContextλ₯Ό μ΄λ»κ² λ§λ€κΉ?)
@SpringBootTest, @DataJpaTest, @WebMvcTest, @JdbcTest λ±μ μ΄λ Έν μ΄μ μ `@ExtendWith (SpringExtension.class)`μ μ΄λ―Έ ν¬ν¨νκ³ μμ΅λλ€.
@ExtendWith (MockitoExtension.class)
Mockitoμ JUnit 5λ₯Ό ν΅ν©νμ¬ λͺ© κ°μ²΄(Mock Objects)λ₯Ό μ½κ² μμ±νκ³ μ¬μ©ν μ μλλ‘ λμμ£Όλ μ΄λ Έν μ΄μ μ λλ€. μ΄ μ΄λ Έν μ΄μ μ μ¬μ©νλ©΄ ν μ€νΈ ν΄λμ€μμ Mockitoμ ν¨κ» λͺ© κ°μ²΄λ₯Ό μ΄κΈ°ννκ³ μ£Όμ ν μ μμ΅λλ€. (`@Mock` μ΄λ Έν μ΄μ νλμ μ΄κΈ°ν)
`@ExtendWith(MockitoExtension.class)`λ₯Ό μ¬μ©νλ©΄ `@Mock` μ΄λ Έν μ΄μ μ νλμ μ μ©νμ¬ λͺ© κ°μ²΄λ₯Ό μμ±νκ³ , `@InjectMocks` μ΄λ Έν μ΄μ μ μ¬μ©νμ¬ λͺ© κ°μ²΄λ₯Ό μ£Όμ ν μ μμ΅λλ€. μ΄λ₯Ό ν΅ν΄ μμ‘΄μ±μ κ°μ§ μ»΄ν¬λνΈλ₯Ό μ½κ² λͺ© κ°μ²΄λ‘ λ체ν μ μμ΅λλ€.
@ExtendWith(MockitoExtension.class)
public class MyServiceTest {
@InjectMocks
private MyService myService;
@Mock
private MyRepository myRepository;
// ν
μ€νΈ μ½λ μμ±
}
λν, μλ λ κ°μ§ λ°©λ²μ λμΌνκ² λμν©λλ€.
// λ°©λ² 1
@ExtendWith(MockitoExtension.class)
public class JUnit5TestClass {...}
// λ°©λ² 2
public class JUnit5TestClass {
@BeforeEach
void setUp(){
//μ€μ! : base class λλ test runnerκ° νμν©λλ€. μ¬κΈ°μλ MockTestλ₯Ό λ£μ΄μ€λλ€.
//μν : @Mock μ΄λ
Έν
μ΄μ
νλμ μ΄κΈ°ν
MockitoAnnotations.openMocks(this);
}
}
@SpringBootTest() - Spring ν΅ν© ν μ€νΈ
`@SpringBootTest` μ΄λ Έν μ΄μ μ JUnit 4μ JUnit 5μ 곡ν΅μ λλ€. μ°¨μ΄μ μ, JUnit5μ @SpringBootTestμλ `@ExtendWith(SpringExtension.class)`κ° μ μΈλμ΄ μμ΅λλ€.
`@SpringBootTest` μ΄λ Έν μ΄μ μ΄ λΆμ΄μλ ν μ€νΈ ν΄λμ€κ° μ€νλλ©΄, `@SpringBootApplication` μ΄λ Έν μ΄μ μ μ°Ύμ λͺ¨λ λΉμ λ‘λν©λλ€. λλΆμ μ€μ μ½λμ²λΌ μμ‘΄μ±μ μ£Όμ νμ¬ μ¬μ© κ°λ₯νλ ν μ€νΈκ° λ§μ΄ 무거μμ§κ² λλ€.
λν μ€μ λΉμ μ£Όμ λ°μ ν μ€νΈνκ² λ¨μΌλ‘μ¨ λ°μ΄ν°λ₯Ό μ½μ νκ±°λ μμ νλ©΄ μ€μ λ°μ΄ν°μ λ³νκ° μκΈΈ μ μλ€. μλνκ² μλλΌλ©΄ κΌ `@Transactional`μ μ΄μ©νμ¬ rollback μ²λ¦¬νλλ‘ νλ€.
@SpringBootTest
public class JUnit5TestClass {
// μμ‘΄μ± μ£Όμ
μ @AutoWiredλ₯Ό μ΄μ©νλ€.
@AutoWired
TestService testservice;
}
μΌλ°μ μΈ μμ‘΄μ± μ£Όμ λ°©λ²μ μλ 4κ°μ§λ₯Ό μ¬μ©νλ€.
1. μμ±μλ₯Ό ν΅ν΄ μμ‘΄μ± μ£Όμ
2. νλλ₯Ό ν΅ν΄μ μμ‘΄μ± μ£Όμ
3. setterλ₯Ό ν΅ν΄μ μμ‘΄μ± μ£Όμ
4. lombokμ μ΄μ©ν final νλμ μμ‘΄μ± μ£Όμ
Junitμμ μμ‘΄μ± μ£Όμ μ νκΈ° μν΄ λ€μν λ°©λ²μ μλνκ² μ§λ§ κ°μ₯ κ°λ¨ν λ°©λ²μ `@AutoWired`λ₯Ό μ΄μ©νλ κ²μ΄λ€. μμ±μλ lombok λ°©μμ μ¬μ©νκ² λλ©΄ μλ¬κ° λ°μν κ²μ΄λ€.
μλ¬κ° λ°μνλ μμΈμ JUnit 5κ° DIλ₯Ό μ€μ€λ‘ μ§μνκΈ° λλ¬Έμ΄λ€. λν DIλ₯Ό μ§μνλ νμ μ΄ μ ν΄μ Έμλ€.
JUnit 5μμ μμ±μλ lombokμ μ΄μ©ν μ μλ μ΄μ λ, JUnitμ΄ μμ±μμ μμ‘΄μ±μ μ£Όμ νλ €κ³ λ¨Όμ κ°μ νκΈ° λλ¬Έμ΄λ€.
π [JUnit] Spring Boot ν μ€νΈνκΈ° (Migration from JUnit4 to Junit5)
π€ Spring MVC ν μ€νΈ vs Spring ν΅ν© ν μ€νΈ
Spring MVC ν μ€νΈ
Spring MVC ν μ€νΈλ μ£Όλ‘ μΉ κ³μΈ΅(controller)μ ν μ€νΈνλ λ° μ¬μ©λ©λλ€.μ£Όλ‘ MockMvcλ₯Ό μ¬μ©νμ¬ μ»¨νΈλ‘€λ¬μ λμ λ° μΉ μμ²-μλ΅ μ£ΌκΈ°λ₯Ό ν μ€νΈν©λλ€.ν μ€νΈ μμλ μ€μ μΉ μλ²λ λ°μ΄ν°λ² μ΄μ€λ₯Ό μ¬μ©νμ§ μμΌλ©°, μ£Όλ‘ μ€νλ§μ @WebMvcTest μ΄λ Έν μ΄μ κ³Ό ν¨κ» μ¬μ©λ©λλ€.ν μ€νΈ λμμ 컨νΈλ‘€λ¬μ κ΄λ ¨λ λ‘μ§μ΄λ©°, μ ν리μΌμ΄μ μ λ€λ₯Έ λΆλΆ(μλΉμ€, 리ν¬μ§ν 리 λ±)μ λͺ© κ°μ²΄(Mock)λ₯Ό μ¬μ©νμ¬ κ°μ§ κ°μ²΄λ‘ λ체ν©λλ€.μ΄λ¬ν ν μ€νΈλ λΉ λ₯΄κ² μ€νλλ©°, μΉ κ³μΈ΅μ μ΄μ μ λ§μΆ₯λλ€.
Spring ν΅ν© ν μ€νΈ
Spring ν΅ν© ν μ€νΈλ μ€νλ§ μ ν리μΌμ΄μ μ μ¬λ¬ κ΅¬μ± μμ(컨νΈλ‘€λ¬, μλΉμ€, 리ν¬μ§ν 리 λ±) κ°μ μνΈ μμ©μ ν μ€νΈνλ λ° μ¬μ©λ©λλ€.μ€μ λ‘ μ ν리μΌμ΄μ 컨ν μ€νΈλ₯Ό λ‘λνκ³ , μ€μ λ°μ΄ν°λ² μ΄μ€μ ν΅ν©νμ¬ λμν©λλ€.μ£Όλ‘ @SpringBootTest μ΄λ Έν μ΄μ κ³Ό ν¨κ» μ¬μ©λλ©°, μ ν리μΌμ΄μ μ 체λ₯Ό μ΄κΈ°ννκ³ μ€μ λΉμ μ¬μ©ν©λλ€.μ ν리μΌμ΄μ μ μ¬λ¬ κ³μΈ΅ κ° μνΈ μμ© λ° ν΅ν© λμμ κ²μ¦νλ©°, λ λ§μ μκ°κ³Ό 리μμ€λ₯Ό νμλ‘ ν©λλ€.
μΉ κ³μΈ΅(controller)μ μ΄μ μ λ λΉ λ₯Έ ν μ€νΈλ₯Ό μνλ€λ©΄ Spring MVC ν μ€νΈλ₯Ό κ³ λ €νκ³ , μ ν리μΌμ΄μ μ 체μ μνΈ μμ© λ° ν΅ν© λμμ κ²μ¦νλ €λ©΄ Spring ν΅ν© ν μ€νΈλ₯Ό κ³ λ €ν μ μμ΅λλ€.
@WebMvcTest()
컨νΈλ‘€λ¬λ₯Ό ν μ€νΈν λ μ£Όλ‘ μ΄μ©λ©λλ€. μ£Όμν μ μ @Service, @Component, @Repository λ±μ μ¬μ©ν μ μμ΅λλ€.
κ·Έ μ΄μ λ λ¨μΌ ν΄λμ€μ ν μ€νΈλ₯Ό μ§ννκΈ° λλ¬ΈμΈλ°, λ§μ½ μ¬μ©νκ³ μΆλ€λ©΄ @MockBeanμ ν΅ν΄ κ°μ κ°μ²΄λ₯Ό λ§λ€μ΄ μ£Όμ΄μΌ ν©λλ€.
(μλ₯Ό λ€μ΄, `@WebMvcTest(DiaryController.class)`λ‘ μ§μ νλ€λ©΄, FriendshipControllerμ κ΄λ ¨λ μ€νλ§ λΉλ€λ§ λ‘λνλ―λ‘ λ€λ₯Έ 컨νΈλ‘€λ¬λ μλΉμ€μ κ΄λ ¨λ λΉλ€μ λ‘λλμ§ μμ΅λλ€.)
@DataJpaTest
@Test
Test μ΄λ Έν μ΄μ μ JUnit 4μ JUnit 5μ 곡ν΅μ λλ€. μ΄λ Έν μ΄μ μ μλ λ©μλλ ν΄λμ€μ ν μ€νΈ μΌμ΄μ€λ₯Ό λνλ λλ€.
@MockBean
@WebMvcTestλ₯Ό μ΄μ©ν ν μ€νΈμμ μ¬μ©ν μ μμ΅λλ€.
Bean 컨ν μ΄λμ κ°μ²΄(Service)κ° μμ΄μΌ λ€λ₯Έ κ°μ²΄(Controller)μ νλ ₯ν μ μλλ°, κ°μ²΄λ₯Ό λ§λ€ μ μλ κ²½μ° @MockBeanμ μ¬μ©ν©λλ€.
@WebMvcTest(RegionController.class)
public class JUnit5TestClass {
@Autowired
private MockMvc mvc;
@MockBean
private RegionService regionService;
@Test
void getRegions() throws Exception {
List<Region> regions = new ArrayList<>();
regions.add(
Region.builder()
.name("Seoul")
.build()
);
given(regionService.getRegions()).willReturn(regions);
mvc.perform(get("/regions"))
.andExpect(status().isOk());
}
}
@Mock
mock κ°μ²΄λ₯Ό μμ±ν©λλ€.
@InjectMocks
@Mockλ‘ μ£Όμμ΄ λ¬λ¦° mock κ°μ²΄λ₯Ό @InjectMocksλ‘ μ£Όμμ΄ λ¬λ¦° κ°μ²΄μ μ£Όμ μν¬ μ μμ΅λλ€. μ€λ¬΄μμλ Service ν μ€νΈ mock κ°μ²΄μ DAO mock κ°μ²΄λ₯Ό μ£Όμ μμΌ μ¬μ©νλ€.
public class MembmerServiceTest{
@Mock
MemberDao memberDao;
@InjectMocks
MemberService memberService;
@Test
public void test(){
when(memberDao.getMemberCount()).thenReturn(0);
Member member = new Member("corn", 25);
assertThat(memberService.createMember(member), is(member));
}
}
@SpyBean
@BeforeEach / @AfterEach
- ν μ€νΈ ν΄λμ€μ κ° ν μ€νΈ λ©μλλ₯Ό μ€ννκΈ° μ μ μ€νλ©λλ€.
- κ° ν μ€νΈλ₯Ό μμνκΈ° μ§μ /νμ 리μμ€ λλ ν μ€νΈ λ°μ΄ν°λ₯Ό μ€μ νλ €λ κ²½μ° μ¬μ©ν μ μμ΅λλ€.
- μλ₯Ό λ€μ΄, JUnit ν μ€νΈ ν΄λμ€μ 5κ°μ ν μ€νΈ μΌμ΄μ€κ° μλ κ²½μ° @BeforeEach / @AfterEachλ‘ μ£Όμμ΄ λ¬λ¦° λ©μλλ κ° ν μ€νΈ μΌμ΄μ€κ° μ€νλκΈ° μ /νμ 5λ² μ€νλ©λλ€.
@BeforeAll / @AfterAll
- ν μ€νΈ ν΄λμ€μ λͺ¨λ ν μ€νΈ λ©μλκ° μ€νλκΈ° μ /νμ μ€νλ©λλ€.
- ν΄λμ€ μμ€μμ λ°μ΄ν°λ₯Ό ν μ€νΈνλ €λ κ²½μ°μ μ¬μ©ν μ μμ΅λλ€.
- μλ₯Ό λ€μ΄, JUnit ν μ€νΈ ν΄λμ€μ 5κ°μ ν μ€νΈ μΌμ΄μ€κ° μλ κ²½μ° @BeforeAll / @AfterAllλ‘ μ£Όμμ΄ λ¬λ¦° μΌμλλ ν μ€νΈ μΌμ΄μ€κ° μμλκΈ° μ /νμ ν μ€νΈ ν΄λμ€ λΉ ν λ² μ€νλ©λλ€.
@Disabled
νΉμ ν μ€νΈ λ©μλλ₯Ό μ€ννμ§ μλλ‘ μ§μ ν©λλ€. μΌμμ μΌλ‘ ν μ€νΈλ₯Ό λΉνμ±ννκ³ μ ν λ μ¬μ©λ©λλ€.
π μ°Έκ³
[Mockκ³Ό Mockito] @Mock @MockBean
[Spring Boot] Controller λ¨μ ν μ€νΈ (@WebMvcTest, MockMvc)
'π± JAVA & SPRING > Spring' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
[spring-test] standaloneSetup() vs webAppContextSetup() (0) | 2023.11.24 |
---|---|
π€ λ§μ κ°λ°μλ€μ "μ" μ€νλ§μ μ¬μ©ν κΉ? (0) | 2023.09.22 |
μλΈλ¦Ώ νν° & μ€νλ§ μΈν°μ ν° (0) | 2023.09.13 |
Spring MVC ꡬ쑰 λ° λμ μ리 (0) | 2023.09.09 |