JUnit4 #1

Dearยท2025๋…„ 8์›” 12์ผ

TIL

๋ชฉ๋ก ๋ณด๊ธฐ
67/74

๐Ÿ’™ @RunWith(SpringRunner.class)

JUnit์ด ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•  ๋•Œ Spring์˜ ํ…Œ์ŠคํŠธ ์ง€์› ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋„๋ก ์„ค์ •ํ•œ๋‹ค.
@Autowired๋กœ Bean ์ฃผ์ž…, @SpringBootTest ๊ฐ™์€ ์–ด๋…ธํ…Œ์ด์…˜ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.

๐Ÿ’™ @SpringBootTest()

์‹ค์ œ ๋‚ด์žฅ ํ†ฐ์บฃ์„ ๋žœ๋ค ํฌํŠธ๋กœ ๋„์›Œ์„œ ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์„ ๊ตฌ์„ฑํ•œ๋‹ค.
REST API๋ฅผ TestRestTemplate๋กœ ์ง์ ‘ ํ˜ธ์ถœํ•ด ํ…Œ์ŠคํŠธ ํ•  ์ˆ˜ ์žˆ๋‹ค.
๋‹จ์ˆœ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๊ฐ€ ์•„๋‹ˆ๋ผ ์‹ค์ œ ์„œ๋ฒ„ ๊ตฌ๋™์„ ํฌํ•จํ•œ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ์ด๋‹ค.

๐Ÿ’™ RestTemplate

Spring์—์„œ ์ œ๊ณตํ•˜๋Š” HTTP ํด๋ผ์ด์–ธํŠธ

Java ์ฝ”๋“œ์—์„œ ๋‹ค๋ฅธ ์„œ๋ฒ„์˜ REST API๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ์“ฐ๋Š” ๋„๊ตฌ
-> Java ์ฝ”๋“œ๋กœ HTTP ์š”์ฒญ ๋ณด๋‚ด๊ณ , ์‘๋‹ต ๋ฐ›์•„์„œ ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•ด์ฃผ๋Š” ํด๋ž˜์Šค

REST API ํ˜ธ์ถœ ์ „์šฉ

  • GET, POST, PUT, DELETE ๊ฐ™์€ HTTP ๋ฉ”์†Œ๋“œ ์ง€์›
  • ์š”์ฒญ ๋ณธ๋ฌธ๊ณผ ํ—ค๋” ์„ค์ • ๊ฐ€๋Šฅ
  • ์‘๋‹ต์„ ๋ฐ”๋กœ Java ๊ฐ์ฒด๋กœ ๋งคํ•‘ ๊ฐ€๋Šฅ (Jackson) ์‚ฌ์šฉ

๋™๊ธฐ ๋ฐฉ์‹

  • ์š”์ฒญ์„ ๋ณด๋‚ด๋ฉด ์‘๋‹ต์ด ์˜ฌ ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆผ

Spring์—์„œ ๊ธฐ๋ณธ ์ œ๊ณต

  • Spring Web ์˜์กด์„ฑ ์ถ”๊ฐ€ํ•˜๋ฉด ๋ฐ”๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

Spring 5๋ถ€ํ„ฐ๋Š” WebClient ๊ถŒ์žฅ

  • RestTemplate์€ ์œ ์ง€๋ณด์ˆ˜ ๋ชจ๋“œ
  • ๋น„๋™๊ธฐ, ๋ฆฌ์•กํ‹ฐ๋ธŒ ์ฒ˜๋ฆฌ๊ฐ€ ํ•„์š”ํ•˜๋ฉด WebClient ์‚ฌ์šฉ
        RestTemplate restTemplate = new RestTemplate();

        // GET ์š”์ฒญ
        String url = "https://jsonplaceholder.typicode.com/posts/1";
        ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);

        System.out.println("์‘๋‹ต ์ฝ”๋“œ: " + response.getStatusCode());
        System.out.println("์‘๋‹ต ๋ณธ๋ฌธ: " + response.getBody());

๐Ÿ’™ TestRestTemplate

Spring Boot์˜ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ์šฉ HTTP ํด๋ผ์ด์–ธํŠธ

์ผ๋ฐ˜ RestTemplate๊ณผ ๋น„์Šทํ•˜๊ฒŒ ๋™์ž‘ํ•˜์ง€๋งŒ, ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฝ๊ฒŒ ๋งŒ๋“ค์–ด์ง„ ํŠนํ™” ๋ฒ„์ „

Spring Boot์—์„œ ์ž๋™์œผ๋กœ ๋นˆ ์ œ๊ณต

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
๊ฐ™์ด ์„ค์ •ํ•˜๋ฉด @Autowired๋กœ ๋ฐ”๋กœ ์ฃผ์ž…๋ฐ›์•„ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

์‹ค์ œ HTTP ์š”์ฒญ์ฒ˜๋Ÿผ ๋™์ž‘

ํ…Œ์ŠคํŠธ ์„œ๋ฒ„๋ฅผ ๋„์šด ๋’ค,
GET, POST, PUT, DELETE ๊ฐ™์€ HTTP ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ  ์‘๋‹ต์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.

RestTemplate๋ณด๋‹ค ํ…Œ์ŠคํŠธ ์นœํ™”์ 

  • ์ธ์ฆ, ๊ธฐ๋ณธ ํ—ค๋” ์„ค์ •, ์ง๋ ฌํ™”/์—ญ์ง๋ ฌํ™” ๋“ฑ์„ ๋” ์‰ฝ๊ฒŒ ์ ์šฉ ๊ฐ€๋Šฅ
  • ํ…Œ์ŠคํŠธ ์„œ๋ฒ„์˜ ํฌํŠธ ๋ฒˆํ˜ธ๋ฅผ ์ž๋™์œผ๋กœ ๋งคํ•‘ (@LocalServerPort์™€ ํ•จ๊ป˜ ์‚ฌ์šฉ)

๋ชฉ์ 

  • ๋‹จ์œ„ ํ…Œ์ŠคํŠธ: ์„œ๋น„์Šค๋‚˜ ๋ ˆํฌ์ง€ํ† ๋ฆฌ๋งŒ ํ…Œ์ŠคํŠธ
  • ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ: ์‹ค์ œ API ์š”์ฒญ/์‘๋‹ต ํ๋ฆ„๊นŒ์ง€ ๊ฒ€์ฆ
    โ†’ TestRestTemplate์€ ํ›„์ž์ธ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ์šฉ

๐Ÿ’™ RestTemplate vs TestRestTemplate

๊ตฌ๋ถ„RestTemplateTestRestTemplate
๋ชฉ์ ์šด์˜ยท๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ ์™ธ๋ถ€ API ํ˜ธ์ถœํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์—์„œ API ํ˜ธ์ถœ ๋ฐ ๊ฒ€์ฆ
์‚ฌ์šฉ ์œ„์น˜์ผ๋ฐ˜ ์„œ๋น„์Šค ๋กœ์ง@SpringBootTest ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ
๊ธฐ๋ณธ ํฌํŠธ ์—ฐ๊ฒฐ์ˆ˜๋™ ์„ค์ • ํ•„์š”@LocalServerPort์™€ ์—ฐ๋™
ํŠน์ง•๋‹จ์ˆœ HTTP ํ˜ธ์ถœํ…Œ์ŠคํŠธ์šฉ ์ธ์ฆยท์„ค์ •์ด ํŽธ๋ฆฌ

์šด์˜ ์ฝ”๋“œ์—์„œ ์™ธ๋ถ€ API ๋ถ€๋ฅผ ๋•Œ โ†’ RestTemplate
ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ์—์„œ ๋‚ด API ์—”๋“œํฌ์ธํŠธ ํ˜ธ์ถœํ•  ๋•Œ โ†’ TestRestTemplate

์‚ฌ์šฉ ์˜ˆ์‹œ

RestTemplate

์šฐ๋ฆฌ ์„œ๋น„์Šค์—์„œ ๋„ค์ด๋ฒ„ ๋‚ ์”จ API๋ฅผ ํ˜ธ์ถœํ•ด์„œ, ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ€๊ณตํ•ด ํ™”๋ฉด์— ๋ณด์—ฌ์ค˜

@Service
public class WeatherService {
    private final RestTemplate restTemplate = new RestTemplate();

    public WeatherInfo getWeather(String city) {
        return restTemplate.getForObject(
            "https://api.weather.com/today?city=" + city,
            WeatherInfo.class
        );
    }
}

TestRestTemplate

์šฐ๋ฆฌ ์„œ๋น„์Šค /weather API๊ฐ€ ์ž˜ ๋™์ž‘ํ•˜๋Š”์ง€ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์—์„œ ํ™•์ธํ•ด๋ณด์ž

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class WeatherControllerTest {

    @LocalServerPort
    int port;

    @Autowired
    TestRestTemplate restTemplate;

    @Test
    void ๋‚ ์”จ_API_ํ…Œ์ŠคํŠธ() {
        String url = "http://localhost:" + port + "/weather?city=Seoul";
        ResponseEntity<WeatherInfo> response = restTemplate.getForEntity(url, WeatherInfo.class);

        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
    }
}

๐Ÿ’™ @LocalServerPort

๋žœ๋คํ•˜๊ฒŒ ํ• ๋‹น๋œ ์„œ๋ฒ„ ํฌํŠธ ๋ฒˆํ˜ธ๋ฅผ ์ฃผ์ž…

restTemplate ์š”์ฒญ URL์— ์‚ฌ์šฉ๋œ๋‹ค (http://localhost:{port})

profile
์นœ์• ํ•˜๋Š” ๊ฐœ๋ฐœ์ž

0๊ฐœ์˜ ๋Œ“๊ธ€