Hello Controller 테스트 코드 작성하기

1. 패키지 생성

  • [src > main > java] 에 패키지 생성
  • 패키지명은 웹 사이트 주소의 역순으로 생성이 일반적
  • ex) com.choee.service.springboot

2. 패키지 내에 Java 클래스 생성

package com.choee.service.springboot;

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

@SpringBootApplication 
public class Application { // 메인 클래스
    public static void main(String[] args) {SpringApplication.run(Application.class,args);} // SpringApplication.run : 내장 WAS 실행
}

@SpringBootApplication

  • 스프링 부트의 자동 설정
  • 스프링 Bean 읽기와 생성 모두 자동 설정,
  • @SpringBootApplication이 있는 위치부터 설정을 읽어가므로 메인 클래스틑 항상 프로젝트의 최상단에 위치해야한다.

Spring Bean 이란?

  • Spring에 의하여 생성되고 관리되는 자바 객체를 Bean이라고 한다.
  • 참조: melonicedlatte.com/2021/07/11/232800.html

내장 WAS(Web Application Server)란?

  • 별도로 외부에 WAS를 두지 않고 애플리케이션을 실행할 때 내부에서 WAS를 실행하는 것

내장 WAS 이용의 장점

  • 항상 서버에 톰캣을 설치할 필요가 없게 되고, 스프링 부트로 만들어진 Jar 파일(실행 가능한 java 패키징 파일)로 실행하면 된다.
  • 언제 어디서나 같은 환경에서 스프링 부트를 배포할 수 있다.

3. 현재 패키지 하위에 web 패키지 생성

  • 컨트롤러와 관련된 클래스들을 관리하는 패키지

HelloControler 클래스 생성하여 테스트 API 작성

package com.choee.service.springboot.web;

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

@RestController
public class HelloController {

    @GetMapping("/hello")
    public String hello() {
        return "hello";
    }
}

@RestController

  • 컨트롤러를 JSON을 반환하는 컨트롤러로 만들어준다.
  • 이전의 @ResponseBody를 각메소드마다 선언했던 것을 한번에 사용할 수 있게해주는 어노테이션

@GetMapping

  • HTTP Method인 Get의 요청을 받을 수 있는 API를 만들어 준다.
  • 이전엔 @RequestMapping(method = RequestMethod.GET)으로 사용

4. 테스트 코드로 검증

package com.choee.service.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 org.springframework.test.web.servlet.ResultActions;
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 hello가_리턴된다() throws Exception {
        String hello = "hello";

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

@RunWith(SpringRunner.class)

  • 테스트를 진행할 때 Junit에 내장된 실행자 외에 다른 실행자를 실행시킨다.
  • SpringRunner라는 스프링 실행자 사용
  • 스프링 부트와 테스트 JUnit 사이의 연결자 역할을 한다.

@WebMvcTest

  • 여러 스프링 테스트 어노테이션 중, Web(Spring MVC)에 집중할 수 잇는 어노테이션
  • 선언할 경우 @Controller, @ControllerAdvice 등 사용 가능
  • @Service, @Component, @Repository 등 사용 불가

@Autowired

  • 스프링이 관리하는 Bean을 주입 받는다.

private MockMvc mvc

  • 웹 API를 테스트할 때 사용
  • 스프링 MVC 테스트의 시작점
  • 이 클래스를 통해 HTTP GET, POST 등에 대한 테스트를 할 수 있다

mvc.perform(get("/hello"))

  • MockMvc를 통해 /hello 주소로 HTTP GET 요청을 한다.
  • 체이닝일 지원되어(.and) 여러 검증 기능을 이어서 선언할 수 있다.

.andExpect(status().isOk())

  • mvc.perform의 결과를 검증한다
  • HTTP Header의 Status(200,404,500 등)를 검증한다.

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

  • mvc.perform의 결과를 검증한다.
  • 응답 본문의 내용을 검증한다.
  • Controller에서 리턴하는 값이 맞는지 검증

5. 테스트 코드 실행하여 확인

  • 메소드 왼쪽의 화살표 클릭
  • Run 'hello가_리턴된다()' 클릭

테스트 코드 필요성

  • 대부분의 서비스 회사가 테스트 코드에 관해 요구
  • 프로젝트형 코딩 테스트에 단위 테스트 필수조건 요구
  • 테스트 자동화 경험 우대

테스트 코드란?

** TDD vs 단위 테스트(Unit Test) **

TDD

  • 테스트가 주도하는 개발
  • 테스트 코드를 먼저 작성
  • 레드 그린 사이클
  1. 항상 실패하는 테스트를 먼저 작성: Red
  2. 테스트가 통과하는 프로덕션 코드를 작성: Green
  3. 테스트가 통과하면 프로덕션 코드를 리팩토링: Refactor

단위 테스트

  • TDD의 첫 번째 단계인 기능 단위의 테스트 코드를 작성하는 것을 의미
  • TDD와 달리 테스트 코드를 꼭 먼저 작성할 필요 X, 리팩토링 포함 X
  • 순수하게 테스트 코드만 작성하는 것을 의미

테스트 코드를 왜 작성해야 하는가?

  • 단위 테스트는 개발단계 초기에 문제를 발견하게 도와준다.
  • 단위 테스트는 개발자가 나중에 코드를 리팩토링하거나 라이브러리 업그레이드 등에서 기존 기능이 올바르게 작동하는지 확인할 수 있다
  • 단위 테스트는 기능에 대한 불확실성을 감소시킬 수 있다.
  • 단위 테스트는 시스템에 대한 실제 문서를 제공한다. 즉, 단위 테스트 자체가 문서로 사용될 수 있다.

테스트 코드를 작성하면 좋은 점

  1. 톰캣을 내렸다가 다시 실행하는 일을 반복하지 않아도 된다.
  2. 눈으로 검증(수동검증)하지 않고 테스트 코드로 자동검증이 가능하다.
  3. 개발자가 만든 기능을 안전하게 보호해준다.( 규모가 큰 서비스에서 새로운 기능이 추가될 때, 기존 기능이 잘 작동되는 것을 보장해준다.)

테스트 코드 작성을 도와주는 프레임워크: xUnit

  • 가장 대중적인 테스트 프레임워크
  • 개발환경(x)에 따라 Unit 테스트를 도와주는 도구
  • JUnit - Java
  • DBUnit - DB
  • ... 등

1. 개발 도구 선정

1.1 인텔리제이(Intelij IDEA) 장점 및 기능

장점

  • 강력한 추천 기능
  • 다양한 리팩토링과 디버깅 기능
  • 높은 Git 자유도
  • 프로젝트 시작할 때 인덱싱을 하여 파일을 비롯한 자원들에 대한 빠른 검색 속도
  • HTML과 CSS, JS, XML에 대한 강력한 기능 지원
  • 자바, 스프링 부트 버전업에 맞춘 빠른 업데이트

커뮤니티(무료) 기능

  • 자바 개발에 대한 모든 기능 지원
  • Maven, Gradle과 같은 빌드 도구 기능 지원
  • 깃 & 깃허브와 같은 VCS(버전 관리 시스템) 기능 지원
  • 스프링 부트의 경우 톰캣과 같은 별도의 외장 서버 없이 실행 가능

HTML과 CSS, JS에 대한 지원은 하지 않아 다른 개발 도구 or 얼티메이트(유료) 이용

 

 

1.2 인텔리제이 설치 방법

1) 인텔리제이를 바로 내려받지 않고 젯브레인 툴박스 이용
2) 툴박스를 통해 인텔리제이 설치

 

 

툴박스: 젯브레인의 제품 전체를 관리해 주는 데스크톱 앱

  • 모든 제품군의 버전 관리와 JVM 옵션 등 조정할 수 있음
  • 새로운 버전이 나오면 툴박스 앱 안에서 업데이트를 바로 확인해서 진행 가능
  • [설정 -> Settings] : Maximun heap size 설정, 인텔리제이를 실행하는데, 어느 만큼의 메모리를 할당할지를 결정

 

1.3 인텔리제이에서 프로젝트 생성 방법

1) 프로젝트 유형 선택: 그레이들 (Gradle)

2) GroupId와 ArtifactId 등록

  • GroupId: 사용할 도메인를 거꾸로 이용 ex) com.dev-choee.service-a
  • ArtifactId: 프로젝트의 이름 ex) springboot2-webservice

3) 그레이들 옵션 선택: 인텔리제이의 기본 설정값

4) 프로젝트의 디렉토리 위치 선택

  • 기본적으로 ArtifactId가 프로젝트 이름
  • Project location에서 원하는 위치로 수정

 

1.4 그레이들 프로젝트를 스프링부트 프로젝트로 변경하기

build.gradle 파일 열어서 스프링 부트에 필요한 설정 추가

 

1) buildscript 코드 작성

buildscript{ 
    ext{ 
        springBoothVersion = '2.1.7.RELEASE' 
    }
    repositories{
        mavenCentral()
        jcenter() 
    }
    dependencies{  
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")        
    }
}

buildscript

  • 보통 별도의 외부 라이브러리를 가져와야 할 때 사용, repository와 dependencies로 구성

ext

  • build.gradle에서 사용하는 전역변수를 설정하겠다는 의미
  • 여기서springBootVersion 전역변수를 생성하고 그 값을 '2.1.7.RELEASE'로 설정

mavenCentral

  • 기본적으로 많이 사용
  • 단점: 본인이 만든 라이브러리를 업로드하기 위해 많은 과정과 설정 필요하여 공유가 안 되는 상황 발생

jcencer

  • 라이브러리 업로드를 간단하게 한 저장소
  • 인터넷의 jcenter 레파지토리 사용 (https://bintray.com/bintray/jcenter)
  • jcenter에 라이브러리를 업로드하면 mavenCentral에도 업로드될 수 있도록 자동화 가능

dependencies

  • 플러그인의 의존성을 받겠다는 의미
  • spring-boot-gradle-plugin라는 스프링 부트 그레이들 플러그인의 2.1.7.RELEASE를 의존성으로 받도록 설정

 

2) buildscript 이외 코드 작성

  • 앞서 선언한 플러그인 의존성들을 적용할 것인지를 결정하는 코드
apply plugin: 'java' 
apply plugin: 'eclipse' 
apply plugin: 'org.springframework.boot' 
apply plugin: 'io.spring.dependency-management' // !!필수!! 스프링 부트의 의존성들을 관리해 주는 플러그인
  • repositories : 각종 의존성(라이브러리)들을 어떤 원격 저장소에서 받을지를 결정
repositories { 
	mavenCentral() 
}

 

  • 프로젝트 개발에 필요한 의존성들을 선언하는 곳
dependencies { 
	implementation('org.springframework.boot:spring-boot-starter-web') 
	testImplementation('org.springframework.boot:spring-boot-starter-test') 
}

 

  • 인텔리제이에서는 메이븐 저장소의 데이터를 인덱싱해서 관리하기 때문에 의존성 자동완성 가능(ctrl+space)
  • 버전을 명시하지 않아야만 위에서 작성한 "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}"의 버전을 따라간다.
  • 책에서는 compile(), testCompile을 사용하지만, implementation을 사용.

Gradle 의존성 옵션: Compile vs implemaetation

 

[Gradle] implementation vs compile

서론 Gradle dependency 관련해서 검색을 하다보면, 어떤 글에서는 implementation을 사용하고 어떤 글에서는 compile을 사용하는 경우가 있다. 사실 어떻게 사용해도 돌아가긴 해서, 음... 무슨 차이지?하고

bluayer.com

3) build.gradle 변경 반영
인텔리제이 오른쪽 하단 알럿의 Enable Auto-import 클릭하여build.gradle 변경이 있을 때 마다 자동 반영되도록 설정

 

4) 의존성 확인
오른쪽 Gradle 탭을 클릭하여 의존성들이 잘 받아졌는지 확인

 

 

1.5 인텔리제이에서 깃과 깃허브 사용하는 방법

  • VCS(버전 관리 시스템) 선택: Git
  • Git의 원격 저장소 서비스 선택: Github

인텔리제이에서 깃허브 연동

1) Ctrl + Shift + A : Action 검색창 열기
2) share project on github 검색
3) 깃허브 로그인
4) Repository name 설정 후 등록 ( 최초 git ingnore 설정 No)
5) 첫 커밋 팝업창에서 .idea 디렉토리 제외한 후 커밋 ( 실행시 자동으로 생성되는 파일들이므로 깃허브 올릴 필요 없음 )
6) .gitignore파일을 사용하여 .idea 폴더를 앞으로의 모든 커밋 대상에서 제외 처리

  • 인텔리제이에서는 .gitignore 파일에 대한 기본적인 지원이 없음
  • 플러그인에서 .gitignore 지원

 

.ignore 플러그인
지원 기능

  • 파일 위치 자동완성
  • 이그노어 처리 여부 확인
  • 다양한 이그노어 파일 지원(.gitignore, .npmignore, .dockerignore 등)

설치 방법

1) Ctrl + Shift + A : Action 검색창 열기
2) plugins 검색
3) Marketplace 에서 .ignore 설치
4) 인텔리제이를 다시 시작해서 설치한 플러그인 적용 ( 반드시 재시작해야만 함)
5) .gitignore 파일 생성: 프로젝트 이름을 선택한 뒤, 마우스 오른쪽 or Alt + Insert로 New(생성목록) 확인하여 .gitignore 파일 생성
6) 이그노어 처리 후 깃허브에 .gitignore 파일을 푸시하여 반영

이그노어 처리

  • 인텔리제이에서 자동으로 생성되는 파일들을 모두 이그노어 처리
  • .gradle .idea

+ Recent posts