ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Spring Boot] REST API 만들기(10) - XML 요청/응답 구현 및 테스트
    Spring Boot/2.4.x - REST API 만들기 2020. 5. 19. 17:50
    반응형

    스프링에서 제공하는 MarshallingHttpMessageConverter를 사용하여 XML 형식으로 데이터를 교환할 수 있도록 구현하겠습니다. MarshallingHttpMessageConverter는 스프링 OXM을 이용해서 객체와 XML 간의 상호 변환 작업을 합니다.

     

    Spring OXM

    스프링 OXM(Object Xml Mapping)은 XML 문서를 객체로 변환하거나, 객체를 XML 문서로 변환하는 기능을 제공합니다. 객체를 XML로 변환하는 과정은 XML Marshalling이라고 하며, XML을 객체로 변환하는 과정을 XML UnMarshalling이라고 합니다.

    Marshaller와 UnMarshaller 인터페이스는 구분되어 있지만, 실제 스프링에서 제공하는 구현체들은 하나의 클래스에서 두 개의 인터페이스를 모두 구현하고 있습니다. 그래서 구현 클래스 하나만 등록하면 Marshaller와 UnMarshaller 모두 사용할 수 있습니다.

     

    1. pom.xml 의존성 추가

    pom.xml에 spring-oxm에 대한 의존성을 추가하세요. 

    pom.xml

    더보기
    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
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.4.8</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.api</groupId>
        <artifactId>board</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>board</name>
        <description>Demo project for Spring Boot</description>
        <properties>
            <java.version>1.8</java.version>
        </properties>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
     
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
            
            <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-configuration-processor -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-configuration-processor</artifactId>
                <optional>true</optional>
            </dependency>
            
            <!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>2.1.4</version>
            </dependency>
             
            <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>
            
            <!-- https://mvnrepository.com/artifact/org.bgee.log4jdbc-log4j2/log4jdbc-log4j2-jdbc4.1 -->
            <dependency>
                <groupId>org.bgee.log4jdbc-log4j2</groupId>
                <artifactId>log4jdbc-log4j2-jdbc4.1</artifactId>
                <version>1.16</version>
            </dependency>
            
            <!-- JUnit4 사용하기 위해서 Vintage Engine 모듈을 제외 -->
            <dependency>
                <groupId>org.junit.vintage</groupId>
                <artifactId>junit-vintage-engine</artifactId>
                <scope>test</scope>
                <exclusions>
                    <exclusion>
                        <groupId>org.hamcrest</groupId>
                        <artifactId>hamcrest-core</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            
            <!-- https://mvnrepository.com/artifact/org.springframework/spring-oxm -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-oxm</artifactId>
            </dependency>
            
        </dependencies>
     
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
     
    </project>
    cs

     

    2. WebMvcConfig.java 수정

    클라이언트의 요청이 오면 등록된 MessageConverter를 통해서 application/json, application/xml 또는 text/xml 형태 등 요청한 형태로 응답할 수 있습니다. 이때 MessageConverter에 대표적인 것들로 MappingJackson2HttpMessageConverter(application/json 형태로 응답), MarshallingHttpMessageConverter(application/xml 또는 text/xml 형태로 응답)가 있습니다. 이 외에도 다양한 종류의 응답 형태로 변환해 주는 MessageConverter가 있으며, 원하는 형태의 응답을 할 때 필요한 MessageConverter 설정을 추가하면 됩니다.

    application/json, application/xml 또는 text/xml 형태의 응답을 위해 MappingJackson2HttpMessageConverter와 MarshallingHttpMessageConverter를 추가하세요.

    Jaxb2Marshaller는 XML을 객체로 변환하거나 객체를 XML로 변환해주는 라이브러리로 변환이 필요한 객체를 찾는 경우, classesToBeBound 또는 packagesToScan를 사용합니다. classToBeBound는 class를 주입해야 하고 packageToScan는 package를 선언해야 하는데, class를 주입하는 경우 객체가 생성될 때마다 설정을 변경하는 불편함이 있어서 package를 선언하여 변환이 필요한 객체를 찾도록 선언하세요.

    WebMvcConfig.java

    더보기
    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
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    package com.api.board.config;
     
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.ComponentScan.Filter;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
    import org.springframework.http.converter.xml.MarshallingHttpMessageConverter;
    import org.springframework.oxm.jaxb.Jaxb2Marshaller;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
     
    import com.api.board.interceptor.BoardInterceptor;
     
    @ComponentScan(basePackages = {"com.api.board.controller"}, useDefaultFilters = false, includeFilters = {@Filter(Controller.class)})
    @Configuration
    public class WebMvcConfig implements WebMvcConfigurer {
     
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new BoardInterceptor())
                    .addPathPatterns("/**")
                    .excludePathPatterns("/sample/**");
        }
        
        @Bean
        public MappingJackson2HttpMessageConverter mappingJacksonHttpMessageConverter() {
            MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
            converter.setPrettyPrint(true);
            return converter;
        }
        
        @Bean
        public MarshallingHttpMessageConverter marshallingHttpMessageConverter() {
            MarshallingHttpMessageConverter converter = new MarshallingHttpMessageConverter();
            converter.setMarshaller(jaxb2Marshaller());
            converter.setUnmarshaller(jaxb2Marshaller());
            return converter;
        }
        
        @Bean
        public Jaxb2Marshaller jaxb2Marshaller() {
            Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
            marshaller.setPackagesToScan(new String[] { "com.api.board.domain" });
            return marshaller;
        }
    }
    cs

     

    3. Bords.java 추가

    @XmlRootElement 어노테이션과 @XmlElement 어노테이션은 자바 객체에서 XML 또는 XML에서 자바 객체로 변환시킬 때 필요한 정보를 설정할 수 있도록 합니다.

    Boards.java

    더보기
    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
    28
    package com.api.board.domain;
     
    import java.util.List;
     
    import javax.xml.bind.annotation.XmlElement;
    import javax.xml.bind.annotation.XmlRootElement;
     
    @XmlRootElement(name = "boards")
    public class Boards {
     
        private List<Board> boards;
        
        public Boards() {
        }
     
        public Boards(List<Board> boards) {
            setBoards(boards);
        }
     
        @XmlElement(name = "board")
        public List<Board> getBoards() {
            return boards;
        }
     
        public void setBoards(List<Board> boards) {
            this.boards = boards;
        }
    }
    cs

     

    4. Board.java 수정

    Board.java

    더보기
    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
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    package com.api.board.domain;
     
    import javax.xml.bind.annotation.XmlRootElement;
    import javax.xml.bind.annotation.XmlType;
     
    @XmlRootElement(name = "board")
    @XmlType(propOrder = {"board_seq""board_re_ref""board_re_lev""board_re_seq""board_writer""board_subject""board_content""board_hits""del_yn""ins_user_id""ins_date""upd_user_id""upd_date"})
    public class Board {
     
        int board_seq;
        int board_re_ref;
        int board_re_lev;
        int board_re_seq;
        String board_writer;
        String board_subject;
        String board_content;
        int board_hits;
        String del_yn;
        String ins_user_id;
        String ins_date;
        String upd_user_id;
        String upd_date;
     
        public int getBoard_seq() {
            return board_seq;
        }
     
        public void setBoard_seq(int board_seq) {
            this.board_seq = board_seq;
        }
     
        public int getBoard_re_ref() {
            return board_re_ref;
        }
     
        public void setBoard_re_ref(int board_re_ref) {
            this.board_re_ref = board_re_ref;
        }
     
        public int getBoard_re_lev() {
            return board_re_lev;
        }
     
        public void setBoard_re_lev(int board_re_lev) {
            this.board_re_lev = board_re_lev;
        }
     
        public int getBoard_re_seq() {
            return board_re_seq;
        }
     
        public void setBoard_re_seq(int board_re_seq) {
            this.board_re_seq = board_re_seq;
        }
     
        public String getBoard_writer() {
            return board_writer;
        }
     
        public void setBoard_writer(String board_writer) {
            this.board_writer = board_writer;
        }
     
        public String getBoard_subject() {
            return board_subject;
        }
     
        public void setBoard_subject(String board_subject) {
            this.board_subject = board_subject;
        }
     
        public String getBoard_content() {
            return board_content;
        }
     
        public void setBoard_content(String board_content) {
            this.board_content = board_content;
        }
     
        public int getBoard_hits() {
            return board_hits;
        }
     
        public void setBoard_hits(int board_hits) {
            this.board_hits = board_hits;
        }
     
        public String getDel_yn() {
            return del_yn;
        }
     
        public void setDel_yn(String del_yn) {
            this.del_yn = del_yn;
        }
     
        public String getIns_user_id() {
            return ins_user_id;
        }
     
        public void setIns_user_id(String ins_user_id) {
            this.ins_user_id = ins_user_id;
        }
     
        public String getIns_date() {
            return ins_date;
        }
     
        public void setIns_date(String ins_date) {
            this.ins_date = ins_date;
        }
     
        public String getUpd_user_id() {
            return upd_user_id;
        }
     
        public void setUpd_user_id(String upd_user_id) {
            this.upd_user_id = upd_user_id;
        }
     
        public String getUpd_date() {
            return upd_date;
        }
     
        public void setUpd_date(String upd_date) {
            this.upd_date = upd_date;
        }
    }
    cs

     

    5. BoardController.java 수정

    Spring OXM에서 사용할 XML Marshaller와 UnMarshaller는 JAXB를 사용하겠습니다. JAXB에서는 List<E> 형태의 객체를 XML로 변환할 수 없고, JSON과는 다르게 XML은 Root Element가 필요합니다. 그래서 Boards라는 클래스를 생성하여 게시글 목록 조회 시 리턴 타입으로 사용해야 합니다.

    BoardController.java

    더보기
    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
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    package com.api.board.controller;
     
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.http.HttpStatus;
    import org.springframework.web.bind.annotation.DeleteMapping;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.PutMapping;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseStatus;
    import org.springframework.web.bind.annotation.RestController;
     
    import com.api.board.domain.Board;
    import com.api.board.domain.Boards;
    import com.api.board.service.BoardService;
     
    @RequestMapping("/board")
    @RestController
    public class BoardController {
     
        @Autowired
        private BoardService boardService;
     
        /** 게시글 목록 조회 */
        @GetMapping
        public Boards getBoardList() throws Exception {
            
            Boards boards = new Boards();
            boards.setBoards(boardService.getBoardList());
            
            return boards;
        }
     
        /** 게시글 상세 조회 */
        @GetMapping("/{board_seq}")
        public Board getBoardDetail(@PathVariable("board_seq"int board_seq) throws Exception {
            return boardService.getBoardDetail(board_seq);
        }
     
        /** 게시글 등록  */
        @ResponseStatus(value = HttpStatus.CREATED)
        @PostMapping
        public Board insertBoard(@RequestBody Board board) throws Exception {
     
            boardService.insertBoard(board);
     
            int boardSeq = board.getBoard_seq();
     
            Board boardDetail = boardService.getBoardDetail(boardSeq);
     
            return boardDetail;
        }
     
        /** 게시글 수정 */
        @ResponseStatus(value = HttpStatus.OK)
        @PutMapping("/{board_seq}")
        public Board updateBoard(@PathVariable("board_seq"int board_seq, @RequestBody Board board) throws Exception {
     
            boardService.updateBoard(board);
     
            Board boardDetail = boardService.getBoardDetail(board_seq);
     
            return boardDetail;
        }
     
        /** 게시글 삭제  */
        @ResponseStatus(value = HttpStatus.OK)
        @DeleteMapping("/{board_seq}")
        public Board deleteBoard(@PathVariable("board_seq"int board_seq) throws Exception {
     
            boardService.deleteBoard(board_seq);
     
            Board deleteBoard = new Board();
            deleteBoard.setBoard_seq(board_seq);
     
            return deleteBoard;
        }
    }
    cs

     

    6. Controller 테스트

    JSON 형식으로 요청/응답 값을 테스트하는 BoardControllerTest 클래스를 BoardControllerAsJsonTest 클래스로 명칭만 변환하고, XML 형식으로 요청/응답 값을 테스트하는 BoardControllerAsXmlTest. 클래스를 추가하세요.

    BoardControllerAsJsonTest.java

    더보기
    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
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    package com.api.board.controller;
     
    import static org.junit.Assert.assertEquals;
    import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
     
    import java.io.IOException;
     
    import org.junit.Before;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.json.JsonParseException;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.http.MediaType;
    import org.springframework.test.annotation.Rollback;
    import org.springframework.test.context.junit4.SpringRunner;
    import org.springframework.test.context.web.WebAppConfiguration;
    import org.springframework.test.web.servlet.MockMvc;
    import org.springframework.test.web.servlet.MvcResult;
    import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
    import org.springframework.test.web.servlet.setup.MockMvcBuilders;
    import org.springframework.transaction.annotation.Transactional;
    import org.springframework.web.context.WebApplicationContext;
    import org.springframework.web.filter.CharacterEncodingFilter;
     
    import com.api.board.domain.Board;
    import com.api.board.service.BoardServiceTest;
    import com.fasterxml.jackson.core.JsonProcessingException;
    import com.fasterxml.jackson.databind.JsonMappingException;
    import com.fasterxml.jackson.databind.ObjectMapper;
     
    @WebAppConfiguration
    @Transactional
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class BoardControllerAsJsonTest {
     
        Logger logger = LoggerFactory.getLogger(BoardServiceTest.class);
     
        private MockMvc mockMvc;
     
        @Autowired
        WebApplicationContext webApplicationContext;
     
        public String mapToJson(Object obj) throws JsonProcessingException {
            ObjectMapper objectMapper = new ObjectMapper();
            return objectMapper.writeValueAsString(obj);
        }
     
        public <T> T mapFromJson(String json, Class<T> clazz) throws JsonParseException, JsonMappingException, IOException {
            ObjectMapper objectMapper = new ObjectMapper();
            return objectMapper.readValue(json, clazz);
        }
     
        @Before
        public void setUp() {
            mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
                                     .addFilters(new CharacterEncodingFilter("UTF-8"true))
                                     .alwaysDo(print())
                                     .build();
        }
        
        int boardSeq = 0;
        
        /** 게시글 목록 조회 시 응답 값이 200이면 테스트 통과 */
        @Test
        public void testGetBoardList() {
     
            try {
                
                MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.get("/board")
                                             .accept(MediaType.APPLICATION_JSON_VALUE))
                                               .andReturn();
                    
                assertEquals(200, mvcResult.getResponse().getStatus());
     
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
     
        /** 게시글 상세 조회 시 응답 값이 200이면 테스트 통과 */
        @Test
        public void testGetBoardDetail() {
            
            try {
                
                if (boardSeq != 0) {
                    
                    MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.get("/board/" + boardSeq)
                                                 .accept(MediaType.APPLICATION_JSON_VALUE))
                                                 .andReturn();
     
                    assertEquals(200, mvcResult.getResponse().getStatus());
                }
                
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
     
        /** 게시글 등록 시 응답 값이 201이면 테스트 통과 */
        @Rollback(true)
        @Test
        public void testInsertBoard() throws Exception {
     
            Board insertBoard = new Board();
            insertBoard.setBoard_writer("게시글 작성자 등록");
            insertBoard.setBoard_subject("게시글 제목 등록");
            insertBoard.setBoard_content("게시글 내용 등록");
     
            MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.post("/board")
                                         .contentType(MediaType.APPLICATION_JSON_VALUE)
                                         .content(this.mapToJson(insertBoard)))
                                         .andReturn();
     
            assertEquals(201, mvcResult.getResponse().getStatus());
        }
     
        /** 게시글 수정 시 응답 값이 200이면 테스트 통과 */
        @Rollback(true)
        @Test
        public void testUpdateBoard() {
            
            try {
                
                if (boardSeq != 0) {
                     
                    Board updateBoard = new Board();
                    updateBoard.setBoard_seq(boardSeq);
                    updateBoard.setBoard_subject("게시글 제목 수정");
                    updateBoard.setBoard_content("게시글 내용 수정");
             
                    MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.put("/board/" + boardSeq)
                                                 .contentType(MediaType.APPLICATION_JSON_VALUE)
                                                 .content(this.mapToJson(updateBoard)))
                                                 .andReturn();
                 
                    assertEquals(200, mvcResult.getResponse().getStatus());
                } 
                
            } catch (Exception e) {
                e.printStackTrace();
            }     
        }
     
        /** 게시글 삭제 시 응답 값이 200이면 테스트 통과 */
        @Rollback(true)
        @Test
        public void testDeleteBoard() { 
     
            try {
                
                if (boardSeq != 0) {
                    
                    MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.delete("/board/" + boardSeq))
                                                 .andReturn();
             
                    assertEquals(200, mvcResult.getResponse().getStatus());
                }
                
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    cs

     

    BoardControllerAsXmlTest.java

    더보기
    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
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    package com.api.board.controller;
     
    import static org.junit.Assert.assertEquals;
    import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
     
    import java.io.StringWriter;
     
    import javax.xml.transform.stream.StreamResult;
     
    import org.junit.Before;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.http.MediaType;
    import org.springframework.oxm.jaxb.Jaxb2Marshaller;
    import org.springframework.test.annotation.Rollback;
    import org.springframework.test.context.junit4.SpringRunner;
    import org.springframework.test.context.web.WebAppConfiguration;
    import org.springframework.test.web.servlet.MockMvc;
    import org.springframework.test.web.servlet.MvcResult;
    import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
    import org.springframework.test.web.servlet.setup.MockMvcBuilders;
    import org.springframework.web.context.WebApplicationContext;
    import org.springframework.web.filter.CharacterEncodingFilter;
     
    import com.api.board.domain.Board;
    import com.api.board.service.BoardServiceTest;
     
    @WebAppConfiguration
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class BoardControllerAsXmlTest {
     
        Logger logger = LoggerFactory.getLogger(BoardServiceTest.class);
     
        private MockMvc mockMvc;
     
        @Autowired
        WebApplicationContext webApplicationContext;
     
        @Autowired
        Jaxb2Marshaller jaxb2Marshaller;
     
        public String mapToXml(Object obj) throws Exception {
            StringWriter writer = new StringWriter();
            jaxb2Marshaller.marshal(obj, new StreamResult(writer));
            String content = writer.toString();
            return content;
        }
     
        @Before
        public void setUp() {
            mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
                                     .addFilters(new CharacterEncodingFilter("UTF-8"true))
                                     .alwaysDo(print())
                                     .build();
        }
     
        int boardSeq = 0;
        
        /** 게시글 목록 조회 시 응답 값이 200이면 테스트 통과 */
        @Test
        public void testGetBoardList() { 
     
            try {
                
                MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.get("/board")
                         .accept(MediaType.APPLICATION_XML))
                         .andReturn();
     
                assertEquals(200, mvcResult.getResponse().getStatus());
     
            } catch (Exception e) {
                e.printStackTrace();
            }       
        }
        
        /** 게시글 상세 조회 시 응답 값이 200이면 테스트 통과 */
        @Test
        public void testGetBoardDetail() {
            
            try {
                
                if (boardSeq != 0) {
                    
                    MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.get("/board/" + boardSeq)
                                                 .accept(MediaType.APPLICATION_XML))
                                                 .andReturn();
     
                    assertEquals(200, mvcResult.getResponse().getStatus());
                }
                
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        
        /** 게시글 등록 시 응답 값이 201이면 테스트 통과 */
        @Rollback(true)
        @Test
        public void testInsertBoard() throws Exception {
     
            Board insertBoard = new Board();
            insertBoard.setBoard_writer("게시글 작성자 등록");
            insertBoard.setBoard_subject("게시글 제목 등록");
            insertBoard.setBoard_content("게시글 내용 등록");
     
            MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.post("/board")
                                         .contentType(MediaType.APPLICATION_XML)
                                         .content(this.mapToXml(insertBoard)))
                                         .andReturn();
     
            assertEquals(201, mvcResult.getResponse().getStatus());
        }
        
        /** 게시글 수정 시 응답 값이 200이면 테스트 통과 */
        @Rollback(true)
        @Test
        public void testUpdateBoard() {
            
            try {
                
                if (boardSeq != 0) {
                     
                    Board updateBoard = new Board();
                    updateBoard.setBoard_seq(boardSeq);
                    updateBoard.setBoard_subject("게시글 제목 수정");
                    updateBoard.setBoard_content("게시글 내용 수정");
             
                    MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.put("/board/" + boardSeq)
                                                 .contentType(MediaType.APPLICATION_XML)
                                                 .content(this.mapToXml(updateBoard)))
                                                 .andReturn();
             
                    assertEquals(200, mvcResult.getResponse().getStatus());
                } 
                
            } catch (Exception e) {
                e.printStackTrace();
            }     
        }
        
        /** 게시글 삭제 시 응답 값이 200이면 테스트 통과 */
        @Rollback(true)
        @Test
        public void testDeleteBoard() { 
     
            try {
                
                if (boardSeq != 0) {
                    
                    MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.delete("/board/" + boardSeq))
                                                 .andReturn();
             
                    assertEquals(200, mvcResult.getResponse().getStatus());
                }
                
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    cs

     

    소스 코드는 Github Repository - https://github.com/tychejin1218/api-board_v1 (branch : section10) 를 참조하세요.

    JAXB - Marshalling, UnMarshalling 사용법 - https://tychejin.tistory.com/135

    Github에서 프로젝트 가져오기 - https://tychejin.tistory.com/33

    반응형

    댓글

Designed by Tistory.