Polpid's World

[Spring]Controller Test 하기 본문

Development/Java

[Spring]Controller Test 하기

폴피드 2017.06.12 23:59

테스트케이스를 만들어서 작업을 하면 소스코드가 수정될 경우 코드를 테스트 해보기가 참 수월하다. 그런데 이 테스트 케이스 작성하는게 생각보다 만만치는 않다. 

실제 DB 를 읽어서 테스트를 해야 하는지. 아니면 Mock 객체를 정의를 해서 사용을 해야 하는지. 실제 DB 를 사용할 경우 저장된 data 가 변경이 되어서 구현했을 당시 테스트 케이스는 Pass였지만 나중에 빌드 시점에 테스트 케이스가 실행될 경우에 Fail 이 나면 어떻게 할것인지. 

생각해보면 그냥 서비스 구현해서 화면 띄우고 버튼 눌러서 테스트 하는것이 더 편할지도 모른다는 생각이 들기도 한다. 

작성할 때마나 서비스 테스트,  repository테스트, 컨트롤러 테스트에 대해서 구글링 하면서 작성을 하다보니 뭔가 남는게 없는것 같아서 샘플을 한번 만들어보기로 했다. 


최근에 필요하기도 했고 나중에 또 써먹을 일도 있을것 같아서 Controller 테스트 케이스를 작성한 것을 공유해 본다.


각각의 구성은 아래와 같이 되어있다. 

(java : 1.8, SpringBoot : 1.5.3)


Book.java

1
2
3
4
5
6
7
8
9
10
11
@Entity
public class Book {
 
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long bookId;
 
    private String title;
 
    // Getter & Setter 생략
}



BookRepository.java
1
2
public interface BookRepository extends JpaRepository<Book, Long>{}
 
cs

BookService.java
1
2
3
public interface BookService {
    Book getBook(Long id);
}
cs


BookServiceImpl.java
1
2
3
4
5
6
7
8
9
10
11
12
@Service
public class BookServiceImpl implements BookService {
 
    @Autowired
    private BookRepository bookRepository;
 
    @Override
    public Book getBook(Long id) {
        return bookRepository.findOne(id);
    }
}
 
cs

BookController.java
1
2
3
4
5
6
7
8
9
10
11
12
@RestController
public class BookController {
 
    @Autowired
    private BookService bookService;
 
    @RequestMapping(value = "/book/{bookId}", method = RequestMethod.GET, produces = "application/json")
    public Book getBook(@PathVariable Long bookId){
        return bookService.getBook(bookId);
    }
}
 
cs


/book/{bookId} 라는 url 로 request 를 보내면 bookId 에 맞는 Book 객체를 리턴해주면 되는 형태이다. 테스트 케이스 없이 테스트 하려면 톰캣으로 띄워놓고 실제로 화면에서 위에 정의한 서비스를 호출하는 컴포넌트를 클릭해서 정상 동작을 하는지 확인해봐야한다. 그러다가 소스에 글자라도 하나 틀리면 수정한다음에 다시 톰캣 재기동을 하는 번거로운 작업을 진행해야 한다. 




이런 번거로움을 피하기 위해 테스트 케이스를 작성해 보았다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@RunWith(SpringRunner.class)
@SpringBootTest
public class BookControllerTest {
 
    private MockMvc mockMvc;
 
    @MockBean
    BookController bookController;
 
    @Before
    public void setup(){
        mockMvc = MockMvcBuilders.standaloneSetup(bookController).build();
    }
 
 
    @Test
    public void getBookTest() throws Exception {
        given(this.bookController.getBook(new Long(1)))
                .willReturn(new Book("Homes"));
 
        mockMvc.perform(get("/book/{bookId}"1))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$['title']", containsString("Homes")))
                .andDo(print());
    }
}
 
cs


BookController를  MockBean으로 정의를 해주었다. 그리고 BookController 의 getBook메소드에 파라메터가 1이 들어왔을 때 리턴 받는 결과를 미리 정의한다. (18~19 라인) 그리고 화면에서 요청하는 것처럼 Request를 수행해준다.  perform에 있는 파라메터를 보면 get 메소드를 호출하게 되며 파라메터로 1값을 넣어서 실행을 한다. OK 응답을 받게 되고 리턴 받는객체의 title이 "Homes"  인지 비교를 한다. 19라인에서 책 이름을 미리 Homes  로 정의 했기때문에 테스트는  Pass가 된다. 마지막에 andDo(print()) 는 실제 수행된 로그가 콘솔창을 통해 볼수 있도록 처리해 준것이다.


처음에 만들때는 좀 삽질을 하긴 했지만 만들고 보니 앞으로 자주 써먹을것 같다. 앞으로도 바쁘지만 테스트케이스를 만들면서 코드 작성을 하도록 해야겠다.


참고로 위 소스를 작성한 gradle.build 파일은 아래와 같다.


1
2
3
4
5
6
7
8
9
10
dependencies {
    compile('org.springframework.boot:spring-boot-starter-web')
    compile('org.springframework.boot:spring-boot-starter-data-jpa')
 
    runtime('group:com.h2database:h2');
 
    testCompile('group:com.jayway.jsonpath:json-path')
 
    testCompile('org.springframework.boot:spring-boot-starter-test')
}
cs


'Development > Java' 카테고리의 다른 글

[OAuth] Oauth의 간략한 흐름.  (0) 2017.07.04
[Spring Security]간단 Spring Security  (0) 2017.06.27
[Spring]Controller Test 하기  (0) 2017.06.12
[Spring]Jasypt 를 이용한 properties 암호화  (6) 2017.04.25
[SpringCloud]Spring Config..  (0) 2016.01.26
spring Cache  (0) 2015.12.05
0 Comments
댓글쓰기 폼