@Component : 클래스 위에 이 어노테이션을 선언하면 스프링 빈으로 등록되어짐.
@Autowired : 스프링 빈에서 해당하는 객체를 찾아 DI해줌
@SpyBean : Test Code에서는 스프링 빈을 사용할 수 없으므로 . 이 어노테이션을 이용해서 유사 스프링 빈을 사용할 수 있게 함 .
@SpyBean(RestaurantRepositoryImpl.class)
private RestaurantRepository restaurantRepository;
Jackson ( Java 객체를 Json으로 , Json객체를 Java 객체로 받을 수 있게 해주는 라이브러리 )
스프링 부트 기본 장착. 객체의 필드명을 Json으로 돌리는것이 아닌
getter가 붙은 것만 Json 객체로 만들어줌.
public class Restaurant {
private String name;
private String address;
private Long id;
private List<MenuItem> menuItems = new ArrayList<>();
public Restaurant(){
}
public Restaurant(Long id,String name,String address) {
this.name=name;
this.address=address;
this.id = id;
}
public Long getId(){
return id;
}
public String getName(){
return name;
}
public String getAddress(){
return address;
}
public String getInformation() {
return getName()+" in "+getAddress();
}
public List<MenuItem> getMenuItems(){
return menuItems;
}
public void addMenuItem(MenuItem menuItem) {
menuItems.add(menuItem);
}
public void setMenuItems(List<MenuItem> menuItems) {
for(MenuItem menuItem : menuItems){
addMenuItem(menuItem);
}
}
}
이런 클래스가 있다면
Id , Name , Address , Information , MenuItems 에 대해서 JSON으로 만들어준다.
MenuItems의 경우 배열 형태인데 이 경우엔 , MenuItems의 요소 Menu의 getter에 따라 다시 달라진다.
public class MenuItem {
private String name;
public MenuItem(String name) {
this.name=name;
}
public String getName(){
return name;
}
}
반대로 Json을 받아야할 경우에는
@PostMapping("/api/members")
public void newMember(@RequestBody RegisterRequest regReq) {
...
};
@RequestBody 어노테이션과 Json 형태에 맞는 도메인 객체를 대입하면 알아서 객체로 변환해서 넘겨줌 .
테스트를 위한 가짜 객체
@Mock : 테스트에 쓰일 가짜 객체를 만들어냄.
@MockBean : SpringBoot-test에서 제공하는 어노테이션.
@Mock은 그냥 가짜객체를 만들어 준다면
@MockBean은 가짜 객체를 Spring context 에 넣어 빈 객체롤 만들어준다.
예시
@RunWith(SpringRunner.class)
@WebMvcTest(RestaurantController.class)
public class RestaurantControllerTests {
@Autowired
private MockMvc mvc;
@MockBean
private RestaurantService restaurantService;
@Test
public void list(){
try {
List<Restaurant> restaurants = new ArrayList<Restaurant>();
restaurants.add(new Restaurant(1004L,"Bob zip","Seoul"));
given(restaurantService.getRestaurants()).willReturn(restaurants);
mvc.perform(get("/restaurants"))
.andExpect(status().isOk())
.andExpect((content()
.string(containsString("\"id\":1004"))));
} catch (Exception e) {
e.printStackTrace();
}
}
...
}
@Mock이나 @MockBean으로 만들어낸 가짜 객체는
항상 given 메소드를 통해서 , 가짜 객체가 어떤 값을 내 뱉는지 정의해줘야만한다.
가짜 객체이기 때문에 , 어떤 값을 내뱉어야 하는지 모르기 때문에 우리가 정의를 내려줘야만 한다.
given은 리턴하는 Mock을 만들었다면 verify는 수행후의 값을 검증 ( ex ) http post 요청후 객체가 들어가는지 )
를 검증하는 역할을 수행한다.
@Test
public void create(){
try {
Restaurant restaurant = new Restaurant(1234L,"BeRyong","Seoul");
mvc.perform(post("/restaurants")
.contentType(MediaType.APPLICATION_JSON)
.content(" {\"name\":\"Beryong\",\"address\":\"Busan\"}"))
.andExpect(status().isCreated())
.andExpect(header().string("location","/restaurants/1234"));
verify(restaurantService).addRestaurant(any());
} catch (Exception e) {
e.printStackTrace();
}
}
이 코드는 restaurants로 post요청을 보내고, 헤더에 restaurants/1234가 들어왔는지 검증하고
또 restaurantService에 객체가 들어갈 수 잇는지를 검증하는 코드이다.. ?? Junit 책을 따로 보는게 낫겠다
Mock에서 post로 Json을 보낼때에는
content에 Json String을 그리고 헤더에 contentType을 넣어야 함으로. contentType, 타입은 MediaType에 정의되어져 있음.
JSon 형식으로 서버 코드도 응답할때 사용함.
@GetMapping("/api/member/{id}")
public ResponseEntity<Object> member(@PathVariable Long id){
...
return ResponseEntity.status(HttpStatus.OK).body( ... );
}
body에는 응답할 Json이 , status에는 응답할 코드를 적으면 완료.
만약 body없이 보낼려고 한다면 .build()를 사용하면 된다 .
ResponseEntity.created()는 , 보내는 Http 헤더의 Location 에 전달할 URI를 전달할때 쓰인다.
주로 201(Created) 경우일때 사용한다.
@PostMapping("/restaurants")
public ResponseEntity<?> create() throws URISyntaxException {
URI location = new URI("/restaurants/1234");
return ResponseEntity.created(location).body("");
}