Day 2

์ €๋ฒˆ ์‹œ๊ฐ„์— ์ด์–ด์„œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ด๋ณด๊ธฐ ์œ„ํ•œ ๊ณผ์ •

๐Ÿ‘‰์ €๋ฒˆ์— ๋งŒ๋“ค์—ˆ๋˜ ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•œ ์ฝ”๋“œ๋ฅผ ๊ฒ€์ฆ

ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด์„œ๋Š”

  • src/test/java ๋””๋ ‰ํ† ๋ฆฌ๋กœ ๊ฐ€์„œ

  • ํ…Œ์ŠคํŠธํ•˜๋ ค๋Š” ์ฝ”๋“œ๊ฐ€ ๋“ค์–ด์žˆ๋Š” ํŒจํ‚ค์ง€์™€ ๋˜‘๊ฐ™์€ ํŒจํ‚ค์ง€๋ฅผ ์ƒ์„ฑํ•˜๊ณ 

  • ํ…Œ์ŠคํŠธํ•˜๋ ค๋Š” ํด๋ž˜์Šค์˜ ์ด๋ฆ„์— Test๋ฅผ ๋ถ™ํžŒ ์ด๋ฆ„์œผ๋กœ ํ…Œ์ŠคํŠธ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค

src/test/java/com/kyu/book/springboot/HelloControllerTest.class

package com.kyu.book.springboot;

import com.kyu.book.springboot.web.HelloController;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@RunWith(SpringRunner.class)
@WebMvcTest(controllers = HelloController.class)
public class HelloControllerTest {
    @Autowired
    private MockMvc mvc;

    @Test
    public void REHello() throws Exception{
        String hello = "hello";

        mvc.perform(get("/hello"))
                .andExpect(status().isOk())
                .andExpect(content().string(hello));
    }
}

@RunWith(SpringRunner.class)

  • ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•  ๋•Œ JUnit์— ๋‚ด์žฅ๋œ ์‹คํ–‰์ž ์™ธ์— ๋‹ค๋ฅธ ์‹คํ–‰์ž๋ฅผ ์‹คํ–‰

  • ์—ฌ๊ธฐ์„œ๋Š” SpringRunner๋ผ๋Š” ์Šคํ”„๋ง ์‹คํ–‰์ž๋ฅผ ์‚ฌ์šฉ

  • ์Šคํ”„๋ง ๋ถ€ํŠธ ํ…Œ์ŠคํŠธ์™€ JUnit ์‚ฌ์ด์˜ ์—ฐ๊ฒฐ์ž ์—ญํ• ์„ ์ˆ˜ํ–‰

@WebMvcTest

  • ์„ ์–ธํ•˜๊ฒŒ ๋˜๋ฉด โ†’ @Controller, @ControllerAdvice ๋“ฑ์˜ annotation์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ

    • @Service, @Repository, @Component๋“ฑ์˜ annotation์€ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Œ

  • ์—ฌ๋Ÿฌ ์Šคํ”„๋ง annotation์ค‘์—์„œ Web์— ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ๋Š” annotation์ด๋‹ค

  • ์—ฌ๊ธฐ์—์„œ๋Š” ์ปจํŠธ๋กค๋Ÿฌ๋งŒ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์„ ์–ธํ•จ

@Autowired

  • ์Šคํ”„๋ง์ด ๊ด€๋ฆฌํ•˜๋Š” Bean์„ ์ฃผ์ž…๋ฐ›๋Š”๋‹ค

Mockmvc

  • ์›น API๋ฅผ ํ…Œ์ŠคํŠธํ•  ๋•Œ ์‚ฌ์šฉํ•จ

  • ์Šคํ”„๋ง MVC ํ…Œ์ŠคํŠธ์˜ ์‹œ์ž‘์ 

  • ์ด ํด๋ž˜์Šค๋ฅผ ํ†ตํ•ด HTTP GET, POST ๋“ฑ์— ๋Œ€ํ•œ API ํ…Œ์ŠคํŠธ๋ฅผ ํ•  ์ˆ˜ ์žˆ์Œ

  • perform(get("/hello"))

    • MockMvc๋ฅผ ํ†ตํ•ด /hello ์ฃผ์†Œ๋กœ http get์š”์ฒญ

    • ๋ฉ”์†Œ๋“œ ์ฒด์ด๋‹์ด ๊ฐ€๋Šฅํ•ด ์—ฌ๋Ÿฌ ๊ฒ€์ฆ์„ ์ด์–ด์„œ ๊ฐ€๋Šฅ

      • andExpect(status().isOk())

        • perform์˜ ๊ฒฐ๊ณผ๊ฐ’์„ ๊ฒ€์ฆ

        • http header์˜ status๋ฅผ ๊ฒ€์ฆํ•œ๋‹ค โ†’ 200, 404, 500์™€ ๊ฐ™์ด ์ƒํƒœ ๊ฒ€์ฆ

        • isOk()๋Š” ์ƒํƒœ ์ฝ”๋“œ๊ฐ€ 200์ธ์ง€ ์•„๋‹Œ์ง€๋ฅผ ๊ฒ€์ฆ

      • andExpect(content().string(hello))

        • mvc.perform์˜ ๊ฒฐ๊ณผ๋ฅผ ๊ฒ€์ฆ

        • ์‘๋‹ต ๋ณธ๋ฌธ์˜ ๋‚ด์šฉ์„ ๊ฒ€์ฆํ•œ๋‹ค

        • Controller(ํ…Œ์ŠคํŠธํ•˜๋Š” ์ฝ”๋“œ)์—์„œ hello๋ฅผ ๋ฆฌํ„ดํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด ๊ฐ’์ด ๋งž๋Š”์ง€ ํ™•์ธ

๐Ÿ‘‰Lombok

gradle์— ์ถ”๊ฐ€

  • compile('org:projectlombock:lombok')

plugins์— ์ถ”๊ฐ€

๋กฌ๋ณต์€ ํ”„๋กœ์ ํŠธ๋งˆ๋‚˜ ์„ค์ •์„ ํ•ด์ค˜์•ผํ•จ โ‡’ build.gradle์— ์ถ”๊ฐ€ / Settings > Build > Compiler > Annotation processors > Enable annotation processing


์œ„์˜ ๋ฐฉ์‹์œผ๋กœ gradle์— ์ถ”๊ฐ€ํ•˜๋ ค๋‹ˆ๊นŒ ์•ˆ๋จ

๊ทธ๋ž˜์„œ

build.gradle์˜ compileํ•˜๋Š” dependencies์— ์•„๋ž˜์™€ ๊ฐ™์ด ๋„ฃ์–ด์ฃผ๋‹ˆ๊นŒ ์ž˜ ๋จ

annotationProcessor("org.projectlombok:lombok")
compileOnly("org.projectlombok:lombok")

๐Ÿ‘‰HelloController์ฝ”๋“œ๋ฅผ ๋กฌ๋ณต์œผ๋กœ ๋ณ€ํ™˜ํ•ด๋ณด๊ธฐ

web์•„๋ž˜์— dtoํŒจํ‚ค์ง€ ์ถ”๊ฐ€

  • ๋ชจ๋“  ์‘๋‹ต dto๋Š” ์ด dtoํŒจํ‚ค์ง€์— ์ถ”๊ฐ€ํ•  ์˜ˆ์ •

src/main/java/com/kyu/book/springboot/web/dto/HelloResponseDto.class

package com.kyu.book.springboot.web.dto;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public class HelloResponseDto {
    private final String name;
    private final int amount;
}

@RequestArgsConstructor

  • ์„ ์–ธ๋œ ๋ชจ๋“  final ํ•„๋“œ๊ฐ€ ํฌํ•จ๋œ ์ƒ์„ฑ์ž๋ฅผ ์ƒ์„ฑํ•ด์คŒ

  • final์ด ์—†๋Š” ํ•„๋“œ๋Š” ์ƒ์„ฑ์ž์— ํฌํ•จ๋˜์ง€ ์•Š์Œ

์œ„์˜ ์ฝ”๋“œ์˜ ํ…Œ์ŠคํŠธ์ฝ”๋“œ

src/main/java/com/kyu/book/springboot/web/dto/HelloResponseDtoTest.class

package com.kyu.book.springboot.web.dto;

import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;

public class HelloResponseDtoTest {
    @Test
    public void lm_fn_test(){
        String name = "test";
        int amount = 1000;

        HelloResponseDto dto = new HelloResponseDto(name, amount);

        assertThat(dto.getName()).isEqualTo(name);
        assertThat(dto.getAmount()).isEqualTo(amount);
    }
}

*์ด ์ฝ”๋“œ๋ฅผ ์ง„ํ–‰ํ•˜๋Š” ๊ณผ์ •์—์„œ lombok์˜ @Getter๊ฐ€ ์ž˜ ์•ˆ๋จน์˜€์—ˆ๋‹ค โ‡’ ๊ทธ๋ž˜์„œ plugin์— ๋“ค์–ด๊ฐ€์„œ lombok์„ disabled > apply ์ดํ›„, enabled > apply ํ•˜๋‹ˆ๊นŒ ์ž˜๋จ

*test ์ง„ํ–‰์ด ๋ถˆ๊ฐ€๋Šฅํ–ˆ๋‹ค โ‡’ github์— ์งˆ๋ฌธํŽ˜์ด์ง€๋ฅผ ๊ฐ€์„œ ์ฐพ์•„๋ณด๋‹ˆ๊นŒ gradle์˜ ๋ฒ„์ „๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ๋‹ค.

์—ฌ์ „ํžˆ ํ˜„์—…์—์„œ๋„ gradle4๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ํ•˜๋‹ˆ๊นŒ ๊ทธ๋ ค๋Ÿฌ๋‹ˆํ•˜๊ณ  gradle4๋ฅผ ์‚ฌ์šฉํ•˜์ž

๋ฒ„์ „์ด ์ด๋ฏธ ์˜ฌ๋ผ๊ฐ€์žˆ์„๋•Œ ๋ณ€๊ฒฝํ•˜๋Š”๋ฐฉ๋ฒ•์€

terminal์„ ์—ด์–ด์„œ

./gradlew wrapper โ€”gradle-version 4.10.2

๋ฅผ ์ ์šฉํ•ด์ฃผ๋ฉด ์ •์ƒ์ ์œผ๋กœ ํ…Œ์ŠคํŠธ๊ฐ€ ์ง„ํ–‰๋œ๋‹ค

assertThat

  • assertj๋ผ๋Š” ํ…Œ์ŠคํŠธ ๊ฒ€์ฆ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ๊ฒ€์ฆ ๋ฉ”์†Œ๋“œ

  • ๊ฒ€์ฆํ•˜๊ณ  ์‹ถ์€ ๋Œ€์ƒ์˜ ๋ฉ”์†Œ๋“œ ์ธ์ž๋ฅผ ๋ฐ›๋Š”๋‹ค

  • ๋ฉ”์†Œ๋“œ ์ฒด์ด๋‹ ์ง€์›๋จ

  • isEqualTo()

    • ๋™๋“ฑํ•œ์ง€ ๋น„๊ตํ•˜๋Š” ๋ฉ”์†Œ๋“œ

    • ๊ฐ’์ด ๊ฐ™์œผ๋ฉด ์„ฑ๊ณต

  • assertj์˜ ์žฅ์  : ๋ฐฑ๊ธฐ์„ ๋‹˜ ์œ ํŠœ๋ธŒ๋ฅผ ๋ณด๊ณ  ๋ฐฐ์šฐ์ž

๐Ÿ‘‰ResponseDto๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ์ถ”๊ฐ€

src/main/java/com/kyu/boot/springboot/web/dto/HelloResponseDto.class์— ์ถ”๊ฐ€๋œ์ฝ”๋“œ

@GetMapping("/hello/dto")
public HelloResponseDto helloDto(@RequestParam("name")String name, 
																		@RequestParam("amount")int amount){
    return new HelloResponseDto(name, amount);
}

@RequestParam

  • ์™ธ๋ถ€์—์„œ API๋กœ ๋„˜๊ธด ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” annotation์ž…๋‹ˆ๋‹ค.

  • ์—ฌ๊ธฐ์—์„œ๋Š” ์™ธ๋ถ€์—์„œ name(@RequestParam("name")) ์ด๋ž€ ์ด๋ฆ„์œผ๋กœ ๋„˜๊ธด ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋ฉ”์†Œ๋“œ ํŒŒ๋ผ๋ฏธํ„ฐ name(String name)์— ์ €์žฅํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

๐Ÿ‘‰์ถ”๊ฐ€๋œ API๋ฅผ ํ…Œ์ŠคํŠธ

src/test/java/com/kyu/book/springboot/web/HelloControllerTest.class์— ์ถ”๊ฐ€๋œ ์ฝ”๋“œ

@Test
public void REHelloDto() throws Exception{
    String name = "hello";
    int amount = 1000;

    mvc.perform(
            get("/hello/dto")
                .param("name", name)
                .param("amount", String.valueOf(amount))
    )
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.name", is(name)))
            .andExpect(jsonPath("$.amount", is(amount)));
}

param

  • API ํ…Œ์ŠคํŠธํ•  ๋•Œ ์‚ฌ์šฉ๋  ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์„ค์ •

  • ๋‹จ, ๊ฐ’์€ String๋งŒ ํ—ˆ์šฉ

  • ๊ทธ๋ž˜์„œ ์ˆซ์ž/๋‚ ์งœ ๋“ฑ์˜ ๋ฐ์ดํ„ฐ๋„ ๋“ฑ๋กํ•  ๋•Œ๋Š” ๋ฌธ์ž์—ด๋กœ ๋ณ€๊ฒฝํ•ด์•ผ๋งŒ ๊ฐ€๋Šฅ

jsonPath

  • JSON ์‘๋‹ต๊ฐ’์„ ํ•„๋“œ๋ณ„๋กœ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ”์†Œ๋“œ

  • $๋ฅผ ๊ธฐ์ค€์œผ๋กœ ํ•„๋“œ๋ช…์„ ๋ช…์‹œ

  • ์—ฌ๊ธฐ์„  name, amount๋ฅผ ๊ฒ€์ฆํ•˜๋‹ˆ $.name, $.amount๋กœ ๊ฒ€์ฆ

*์ž๊พธ ํ…Œ์ŠคํŠธ์‹œ Test events were not received๊ฐ€ ๋œธ

โ‡’ Preference > Build, Execution, Deployment > Build Tools > Gradle๋กœ ์ด๋™ํ•ด์„œ

โ‡’Run test using์„ Intellij IDEA๋กœ ๋ณ€๊ฒฝ

Last updated

Was this helpful?