[springboot-webserivce] GET API test ์ฝ”๋“œ ์ž‘์„ฑ

Updated:

[2020.12.28] ๋ถ€ํ„ฐ ์Šคํ”„๋ง ๋ถ€ํŠธ์™€ AWS๋กœ ํ˜ผ์ž ๊ตฌํ˜„ํ•˜๋Š” ์›น ์„œ๋น„์Šค ์ฑ…์„ ํ†ตํ•ด ์Šคํ”„๋ง ๊ณต๋ถ€๋ฅผ ์‹œ์ž‘ํ–ˆ๋‹ค.

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

๊ทธ๋ž˜์•ผ ๋‚˜์ค‘์— ๋‹ค์‹œ ์ฐพ์•„๋ณด๋ฉฐ ๊ณต๋ถ€ ํ•  ์ˆ˜ ์žˆ์„ํ…Œ๋‹ˆ๊นŒ !!

๐Ÿ— TDD

TDD ๋Š” ํ…Œ์ŠคํŠธ๊ฐ€ ์ฃผ๋„ํ•˜๋Š” ๊ฐœ๋ฐœ ์„ ์˜๋ฏธํ•œ๋‹ค.

๋จผ์ € ๋ฌด์กฐ๊ฑด ์‹คํŒจํ•˜๋Š” ๊ฒฝ์šฐ์˜ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ณ  ๋‹ค์Œ์œผ๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ํ†ต๊ณผํ•˜๋Š” ํ”„๋กœ๋•์…˜ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค.

ํ…Œ์ŠคํŠธ๊ฐ€ ํ†ต๊ณผ๋˜๋ฉด ํ•ด๋‹น ํ”„๋กœ๋•์…˜ ์ฝ”๋“œ๋ฅผ ๋ฆฌํŒฉํ† ๋ง ํ•œ๋‹ค.

์ด ์‚ฌ์ดํด์„ TDD ๋ผ๊ณ  ํ•˜๋Š”๋ฐ ๋จผ์ € TDD ์˜ ์ฒซ ๋ฒˆ์งธ ๋‹จ๊ณ„์ธ ๊ธฐ๋Šฅ ๋‹จ์œ„์˜ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋ ค๊ณ  ํ•œ๋‹ค.

ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ด์œ ๋กœ ๊ฐœ๋ฐœ์— ์žˆ์–ด ํ•„์ˆ˜์ด๋‹ค.

  1. ๊ฐœ๋ฐœ๋‹จ๊ณ„ ์ดˆ๊ธฐ์— ๋ฌธ์ œ๋ฅผ ๋ฐœ๊ฒฌํ•˜๊ฒŒ ๋„์™€์ค€๋‹ค.
  2. ๋ฆฌํŒฉํ† ๋ง์„ ํ•˜๊ฑฐ๋‚˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์—…๊ทธ๋ ˆ์ด๋“œ ๋“ฑ์—์„œ ๊ธฐ์กด ๊ธฐ๋Šฅ์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.
  3. ๊ธฐ๋Šฅ์— ๋Œ€ํ•œ ๋ถˆํ™•์‹ค์„ฑ์„ ๊ฐ์†Œ ์‹œํ‚จ๋‹ค.

์ €์ž์˜ ๊ฒฝํ—˜์„ ์˜ˆ๋กœ ๋“ค์ž๋ฉด ์ €์ž๋Š” ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋ฅผ ๋ฐฐ์šฐ๊ธฐ ์ „์— ๊ฐœ๋ฐœ ๊ณผ์ •์€ ์ด๋Ÿฌํ–ˆ๋‹ค.

  1. ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑ
  2. ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰
  3. Postman ๊ณผ ๊ฐ™์€ API ํ…Œ์ŠคํŠธ ๋„๊ตฌ๋กœ HTTP ์š”์ฒญ
  4. System.out.println() ์„ ํ†ตํ•ด ๋ˆˆ์œผ๋กœ ๊ฒ€์ฆ
  5. ์ฝ”๋“œ ์ˆ˜์ •

์ด๋Ÿฐ ๊ณผ์ •์œผ๋กœ ๊ฐœ๋ฐœ์„ ํ•ด์„œ 3, 4, 5 ๋ฒˆ ๊ณผ์ •์„ ๊ฑฐ์น  ๋•Œ ๋งˆ๋‹ค ํ†ฐ์บฃ์„ ๊ป๋‹ค ์ผœ์•ผํ•˜๋Š” ๋ถˆํŽธํ•จ์ด ์žˆ์—ˆ๋‹ค๊ณ  ํ•œ๋‹ค.

ํ•˜์ง€๋งŒ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด์„œ ์‹คํ–‰ํ•œ๋‹ค๋ฉด ๊ฒ€์ฆ๋„ ์ž๋™์œผ๋กœ ํ•ด์ค„ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์ด๋Ÿฌํ•œ ๋ถˆํŽธํ•จ ๊นŒ์ง€ ์—†์–ด์ง„๋‹ค.

๐Ÿฅฎ JUnit

์•ž์„œ ๋งํ•œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑ์„ ๋„์™€์ฃผ๋Š” ํ”„๋ ˆ์ž„์›Œํฌ๋กœ xUnit ์ด ์žˆ๋‹ค.

x ๋Š” ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์— ๋”ฐ๋ผ ๋ฐ”๋€Œ๊ฒŒ ๋˜๋Š”๋ฐ ๋‚˜๋Š” Java ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— JUnit ์„ ์‚ฌ์šฉํ•œ๋‹ค.

์ตœ์‹ ๋ฒ„์ „์€ ๋ฒ„์ „ 5๊นŒ์ง€ ์žˆ์ง€๋งŒ ๋Œ€๋ถ€๋ถ„์˜ ํšŒ์‚ฌ์—์„œ ๋ฒ„์ „ 4๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์‹ค์Šต์—์„œ๋„ ๋ฒ„์ „ 4๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

๐Ÿง‹ Main ํด๋ž˜์Šค, GET API ์ƒ์„ฑ

ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ ์œ„ํ•ด ์šฐ์„  Main ํด๋ž˜์Šค์™€ GET API ๋ฅผ ๋งŒ๋“ค๋ ค๊ณ  ํ•œ๋‹ค.

src/main/java ํด๋”์— ์›น ์‚ฌ์ดํŠธ ์ฃผ์†Œ ๋ช…์˜ ์—ญ์ˆœ์„ ์ด๋ฆ„์œผ๋กœ ๊ฐ€์ง€๋Š” ํŒจํ‚ค์ง€๋ฅผ ๋งŒ๋“ ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๊ทธ ํŒจํ‚ค์ง€์— Application ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ ๋‹ค.

์ด ํด๋ž˜์Šค๊ฐ€ ์•ž์œผ๋กœ ๋งŒ๋“ค ํ”„๋กœ์ ํŠธ์˜ ๋ฉ”์ธ ํด๋ž˜์Šค๊ฐ€ ๋œ๋‹ค.

package com.boks.springboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

// ์Šคํ”„๋ง ๋ถ€ํŠธ์˜ ์ž๋™ ์„ค์ •, ์Šคํ”„๋ง Bean ์ฝ๊ธฐ์™€ ์ƒ์„ฑ ๋ชจ๋‘ ์ž๋™ ์„ค์ •
// ์ด Annotation ๋ถ€ํ„ฐ ์„ค์ •์„ ์ฝ๊ธฐ ๋•Œ๋ฌธ์— ์ด ํด๋ž˜์Šค๋Š” ํ•ญ์ƒ ํ”„๋กœ์ ํŠธ ์ตœ์ƒ๋‹จ์— ์žˆ์–ด์•ผ ํ•จ
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

SpringApplication.run ๋ฉ”์†Œ๋“œ๋ฅผ ์‹คํ–‰์‹œํ‚ค๋ฉด ๋‚ด์žฅ WAS ๊ฐ€ ์‹คํ–‰๋œ๋‹ค.


๋‹ค์Œ์œผ๋กœ ๋ฐฉ๊ธˆ ๋งŒ๋“ค์—ˆ๋˜ ํŒจํ‚ค์ง€์— ํ•˜์œ„ ํŒจํ‚ค์ง€๋กœ controller ํด๋ž˜์Šค๋“ค์„ ๋‹ด์„ web ํŒจํ‚ค์ง€๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

web ํŒจํ‚ค์ง€์— 127.0.0.1:8080/hello ์ฃผ์†Œ๋กœ GET ์š”์ฒญ์„ ๋ณด๋‚ด๋ฉด hello ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” API ๋ฅผ ๋งŒ๋“ค ๊ฒƒ์ด๋‹ค.

package com.boks.springboot.web;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController  // ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ JSON์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ปจํŠธ๋กค๋Ÿฌ๋กœ ๋งŒ๋“ค์–ด ์คŒ.
public class HelloController {

    @GetMapping("/hello")  // GET ์š”์ฒญ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” API๋ฅผ ๋งŒ๋“ค์–ด ์คŒ.
    public String hello() {
        return "hello";
    }
}

์—ฌ๊ธฐ๊นŒ์ง€๊ฐ€ Main ํด๋ž˜์Šค์™€ GET API ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ณผ์ •์ด์—ˆ๋‹ค.

ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๊ฐ€ ์—†๋‹ค๋ฉด ์ง€๊ธˆ ๋งŒ๋“  API ๋ฅผ ํ…Œ์ŠคํŠธ ํ•˜๊ธฐ ์œ„ํ•ด ๋ฉ”์ธ ํด๋ž˜์Šค๋ฅผ ํ†ตํ•ด WAS ๋ฅผ ์‹คํ–‰ ์‹œํ‚จ ๋’ค

127.0.0.1:8080/hello ์ฃผ์†Œ๋กœ ์ง์ ‘ ์ ‘์† ํ•ด ๋ˆˆ์œผ๋กœ ํ™•์ธํ•ด์•ผ ํ•œ๋‹ค.

ํ•˜์ง€๋งŒ JUnit ์„ ์ด์šฉํ•ด ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ๋งŒ๋“ ๋‹ค๋ฉด WAS ๋ฅผ ์‹คํ–‰ ์‹œํ‚ฌ ํ•„์š”์—†์ด ๊ฒ€์ฆ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค.

๐Ÿง JUnit์„ ํ†ตํ•œ ํ…Œ์ŠคํŠธ์ฝ”๋“œ ์ž‘์„ฑ

์Šคํฌ๋ฆฐ์ƒท 2020-12-29 ์˜คํ›„ 7 44 31

์•ž์„œ ๋งŒ๋“ค์—ˆ๋˜ ํŒจํ‚ค์ง€๋ฅผ ๊ทธ๋Œ€๋กœ test ์— ๋งŒ๋“ค์–ด ์ฃผ์ž.

์ผ๋ฐ˜์ ์œผ๋กœ ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค๋Š” ํ•ด๋‹น ํด๋ž˜์Šค ์ด๋ฆ„ ๋’ค์— Test ๋ฅผ ๋ถ™์ธ๋‹ค๊ณ  ํ•œ๋‹ค.

๋”ฐ๋ผ์„œ HelloControllerTest ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์ž.

package com.boks.springboot.web;


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)  // ์Šคํ”„๋ง ๋ถ€ํŠธ ํ…Œ์ŠคํŠธ์™€ JUnit ์‚ฌ์ด์˜ ์—ฐ๊ฒฐ์ž ์—ญํ• 
@WebMvcTest(controllers = HelloController.class)  // ์—ฌ๋Ÿฌ ์Šคํ”„๋ง ํ…Œ์ŠคํŠธ ์–ด๋…ธํ…Œ์ด์…˜ ์ค‘ web์— ์ง‘์ค‘
public class HelloControllerTest {

    @Autowired  // ์Šคํ”„๋ง์ด ๊ด€๋ฆฌํ•˜๋Š” bean์„ ์ฃผ์ž…
    private MockMvc mvc;  // ์›น API๋ฅผ ํ…Œ์ŠคํŠธ ํ•˜๋Š” ๊ฒฝ์šฐ ์‚ฌ์šฉ, ํ…Œ์ŠคํŠธ์˜ ์‹œ์ž‘์ 

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

        mvc.perform(get("/hello"))  // MockMvc๋ฅผ ํ†ตํ•ด /hello ์ฃผ์†Œ๋กœ GET ์š”์ฒญ
                .andExpect(status().isOk())  // ์ด ์š”์ฒญ์˜ ์ƒํƒœ๋ฅผ ๊ฒ€์ฆ, ์ด ๊ฒฝ์šฐ OK ์ฆ‰ 200 ์ธ์ง€ ํ™•์ธ
                .andExpect(content().string(hello));  // GET์„ ํ†ตํ•ด ๋ฐ›์€ ๊ฐ’์ด hello ์ธ์ง€ ํ™•์ธ
    }
}

์–ด๋…ธํ…Œ์ด์…˜์ด ๋งŽ์•„์„œ ๋ณต์žกํ•ด ๋ณด์ผ ์ˆ˜ ์žˆ์ง€๋งŒ ํฐ ํ‹€์„ ๋ณด์ž๋ฉด

MockMvc ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€์ง€๋Š” mvc ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด perform ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด /hello ์ฃผ์†Œ๋กœ GET ์„ ์š”์ฒญ ํ•œ ๋’ค

์š”์ฒญ์˜ ์ƒํƒœ๋ฅผ status().isOk ๋กœ ๊ฒ€์ฆ์„ ํ•˜๊ณ  GET ์„ ํ†ตํ•ด ๋ฐ›์€ ๊ฐ’์ด hello ์ธ์ง€ ๊ฒ€์‚ฌํ•˜๋Š” ์ฝ”๋“œ์ด๋‹ค.

returnHello ๋ฉ”์†Œ๋“œ๋ฅผ ๋™์ž‘ํ•˜๊ฒŒ ๋˜๋ฉด ํ…Œ์ŠคํŠธ๋ฅผ ์‹œ์ž‘ํ•˜๋Š”๋ฐ ํ…Œ์ŠคํŠธ๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ๋๋‚˜๊ฒŒ ๋˜๋ฉด

์Šคํฌ๋ฆฐ์ƒท 2020-12-29 ์˜คํ›„ 7 51 44

ํ…Œ์ŠคํŠธ ํ†ต๊ณผ๋ฅผ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

status ๊ฐ€ Ok, 200 ์ด ์•„๋‹ˆ๊ฑฐ๋‚˜ GET ์„ ํ†ตํ•ด ๋ฐ›์€ ๊ฐ’์ด hello ๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด Tests Failed ์ด ๋œ๋‹ค.


์ด ๊ฒฐ๊ณผ๋ฅผ ๋ชป๋ฏฟ๊ฒ ๋‹ค.. ์‹ถ์œผ๋ฉด ์‹ค์ œ๋กœ WAS ๋ฅผ ์‹คํ–‰ ์‹œ์ผœ ์ง์ ‘ ํ™•์ธํ•ด๋„ ๋œ๋‹ค.

Application ํด๋ž˜์Šค๋ฅผ ์‹คํ–‰์‹œํ‚จ ๋’ค 127.0.0.1:8080/hello ๋กœ ์ ‘์†์„ ํ•ด๋ณด์ž.

์Šคํฌ๋ฆฐ์ƒท 2020-12-29 ์˜คํ›„ 7 56 14

ํ†ฐ์บฃ์ด 8080 ํฌํŠธ๋กœ ์‹คํ–‰ ๋˜์—ˆ๋‹ค๋Š” ๋ฉ”์‹œ์ง€๋„ ๋ณด์ธ๋‹ค.

์Šคํฌ๋ฆฐ์ƒท 2020-12-29 ์˜คํ›„ 7 56 47

hello ๊ฐ€ ์ž˜ ์ถœ๋ ฅ ๋˜๋Š” ๊ฒƒ๋„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋กœ ํ…Œ์ŠคํŠธ ํ›„ ์ •๋ง๋กœ ๋ชป ๋ฏฟ๊ฒ ๋‹ค ํ•˜๋Š” ๊ฒฝ์šฐ์—๋งŒ ์ด๋ ‡๊ฒŒ ์ง์ ‘ ๋ˆˆ์œผ๋กœ ํ™•์ธ ํ•˜์ž.

์ˆ˜๋™์œผ๋กœ ํ™•์ธ ํ›„ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ํ–‰์œ„๋Š” ์ ˆ๋Œ€ ๊ธˆ์ง€์ด๋‹ค.



Categories:

Updated:

Leave a comment