참고사이트)
UriComponentsBuilder : https://dlwjdcks5343.tistory.com/93
junit 5 : https://www.javacodemonk.com/migrating-spring-boot-tests-from-junit-4-to-junit-5-00aa2839
mockmvc : https://memorynotfound.com/unit-test-spring-mvc-rest-service-junit-mockito/
https://itmore.tistory.com/entry/MockMvc-%EC%83%81%EC%84%B8%EC%84%A4%EB%AA%85
mockmvc 이 NullPointerException 에러뜰때 : https://velog.io/@minholee_93/ERROR-MockMvc-NullPointerException-Spring-Boot-8yk5kgb9q0
@AutoConfigureMockMvc 추가
REST MVC
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 | <?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.2.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>demo</name> <description>Demo project for Spring Boot</description> <properties> <java.version>11</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | package com.example.demo.library; import lombok.*; import java.util.ArrayList; import java.util.List; @Setter @Getter @NoArgsConstructor @AllArgsConstructor @ToString public class Book { private String isbn; private String title; private List<String> authors = new ArrayList<>(); } | cs |
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 | package com.example.demo.library; import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.util.UriComponentsBuilder; import java.net.URI; @Slf4j @RestController @RequestMapping("/books") public class BookController { private final BookService bookService; public BookController(BookService bookService) { this.bookService = bookService; } @GetMapping public Iterable<Book> all(){ return bookService.findAll(); } @GetMapping("/{isbn}") public ResponseEntity<Book> get(@PathVariable("isbn") String isbn){ return bookService.find(isbn).map(ResponseEntity::ok) .orElse(ResponseEntity.notFound().build()); } @PostMapping public ResponseEntity<Book> create(@RequestBody Book book, UriComponentsBuilder uriComponentsBuilder){ log.info("create.tostirng:"+book.toString()); Book created = bookService.create(book); URI newBookUri = uriComponentsBuilder.path("/books/{isbn}").build(created.getIsbn()); //URI newBookUri = UriComponentsBuilder.newInstance().path("/books/{isbn}").build(created.getIsbn()); return ResponseEntity.created(newBookUri).body(created); } } | cs |
1 2 3 4 5 6 7 8 9 | package com.example.demo.library; import java.util.Optional; public interface BookService { Iterable<Book> findAll(); Book create(Book book); Optional<Book> find(String isbn); } | cs |
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 | package com.example.demo.library; import org.springframework.stereotype.Service; import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; @Service public class InMemoryBookService implements BookService { private final Map<String, Book> books = new ConcurrentHashMap<>(); @Override public Iterable<Book> findAll() { return books.values(); } @Override public Book create(Book book) { books.put(book.getIsbn(), book); return book; } @Override public Optional<Book> find(String isbn) { return Optional.ofNullable(books.get((isbn))); } } | cs |
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 | package com.example.demo; import com.example.demo.library.Book; import com.example.demo.library.BookService; import org.hamcrest.Matchers; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.result.MockMvcResultMatchers; import java.util.Arrays; import java.util.List; import java.util.Optional; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.when; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; @ExtendWith(SpringExtension.class) @SpringBootTest @AutoConfigureMockMvc public class BookControllerTest { @Autowired private MockMvc mockMvc; @MockBean private BookService bookService; @Test public void shouldReturnListOfBooks() throws Exception{ List<Book> books = Arrays.asList( new Book("123", "Spring 5 Recipes", Arrays.asList("Marten Deinum", "Josh Long")), new Book("321", "Pro Spring MVC", Arrays.asList("Marten Deinum", "Colin Yates"))); when(bookService.findAll()).thenReturn(books); mockMvc.perform((get("/books"))) .andExpect(status().isOk()) .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) .andExpect(MockMvcResultMatchers.jsonPath("$", Matchers.hasSize(2))) .andExpect(MockMvcResultMatchers.jsonPath("$[*].isbn", Matchers.containsInAnyOrder("123","321"))) .andExpect(MockMvcResultMatchers.jsonPath("$[*].title",Matchers.containsInAnyOrder("Spring 5 Recipes", "Pro Spring MVC"))); } @Test public void shouldReturn404WhenBookNotFound() throws Exception{ when(bookService.find(anyString())).thenReturn(Optional.empty()); mockMvc.perform(get("/books/123")).andExpect(status().isNotFound()); } @Test public void shouldAddBook() throws Exception{ when(bookService.create(any(Book.class))).thenReturn( new Book("123456789", "Test Book Stored", Arrays.asList("T. Author"))); mockMvc.perform(post("/books") .contentType(MediaType.APPLICATION_JSON) .content("{\n" + " \"isbn\":\"123456789\",\n" + " \"title\":\"Test Book Stored\",\n" + " \"authors\":[\"T. Author\"]\n" + "}")) .andExpect(status().isCreated()) .andExpect(header().string("Location","http://localhost/books/123456789")); } } | cs |
인텔리J에서 응답테스트하기
test.http
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | GET http://localhost:8080/books ### GET http://localhost:8080/books/9780061120084 ### GET http://localhost:8080/books/9780618640157 ### POST http://localhost:8080/books Content-Type: application/json { "isbn":"9780618640157", "title":"The Lord of the Rings", "authors":["J.R.R. Tolkien"] } | cs |
파일목록
반응형
'WEB > 스프링 부트 2' 카테고리의 다른 글
Jetty SSL, Http to Https (0) | 2020.02.06 |
---|---|
Spring SSL, Http to Https (0) | 2020.02.05 |
Messages.properties (0) | 2020.02.05 |
타임리프(thymeleaf) (0) | 2020.02.04 |
책1 (0) | 2020.02.03 |