상품 도메인 모델 구현(domain패키지>item패키지>Item 클래스 생성)
int가 아닌 Integer로 설정한 이유 : 값이 안 들어가는 경우도 있기 때문에 null값도 받기 위해서다.
단순히 데이터를 주고받는 경우는 사용할 수도 있지만, 다음과 같은 이유로 @Data 애노테이션을 사용할 주의해야한다! (@Getter, @Setter 정도만 사용하는 것을 추천)
@ToString의 경우 객체의 양방향 연관관계(a->b,b->a)가 있을 때 무한 루프로 호출될 수 있다.
Equals, hashCode도 모든 필드를 다 기준으로 잡는다.
packagehello.itemservice.domain.item;importlombok.Data;importlombok.Getter;importlombok.Setter;@DatapublicclassItem {privateLong id;privateString itemName;privateInteger price;//price가 안들어갈 때도 있다고 가정하기 때문에 null도 받기 위해서privateInteger quantity;publicItem(){ }publicItem(String itemName,Integer price,Integer quantity) {this.itemName= itemName;this.price= price;this.quantity= quantity; }}
2. 아이템 Repository 구현(domain패키지>item패키지>ItemRepository 클래스 생성)
멀티스레드 사용하는 실무 환경에서 여러 스레드가 동시에 접근 가능한 동시성 문제와 스프링 컨테이너에서는 객체가 싱글톤으로 생성되기 때문에 HashMap사용하면 안되고 ConcurrentHashMap 사용해야한다. long 변수도 atomiclong 을 사용해야한다!
상품 전체 조회 findAll() : 아이템 객체들 날 것 그대로 반환해도 되지만 값을 변경해도 ArrayList에 값을 넣고 원래 객체 데이터는 보존하기 위해 ArrayList로 한번 감싼다!
상품 수정 update() : id가 사용되지 않기 때문에 updateParam라는 별도의 객체를 생성하는 것이 맞다! 개발자는 혼란스러워서 id필드가 있는데 왜 업데이트가 안되는지 의문을 가지며 setId로 값을 갱신해버릴 수도 있기 때문이다!
packagehello.itemservice.domain.item;importorg.springframework.stereotype.Repository;importjava.util.ArrayList;importjava.util.HashMap;importjava.util.List;importjava.util.Map;@RepositorypublicclassItemRepository {privatestaticfinalMap<Long,Item> store =newHashMap<>();//staticprivatestaticlong sequence =0L;//static//상품 등publicItemsave(Item item){item.setId(++sequence);//@Data가 제공하는 자동 setter 기능으로 눈에 보이지는 않지만 Setter 존재!store.put(item.getId(),item);return item; }//상품 조회(id)publicItemfindById(Long id){returnstore.get(id); }//상품 조회(전체)publicList<Item> findAll(){returnnewArrayList<>(store.values());//아이템 객체들 반환 }//상품 수정publicvoidupdate(Long itemId,Item updateParam){Item findItem =findById(itemId);findItem.setItemName(updateParam.getItemName());findItem.setPrice(updateParam.getPrice());findItem.setQuantity(updateParam.getQuantity()); }//전체 상품 삭제publicvoidclearStore(){store.clear(); }}
3. ItemRepository 테스트 코드 작성
save() : 상품 생성, ItemRepository에 등록하고 ItemRepository에서 id로 찾은 객체와 같은지 비교.
update() : 상품1 생성(itemId), ItemRepository에 등록. 상품2 생성, 상품2로 상품 수정(itemId,item2)
상품1의 id인 itemId로 ItemRepository 조회했을 때 상품2의 각 속성 값들과 같은지 비교.
(쉽게 말해서 상품1을 상품2로 업데이트했기 때문에 상품1의 id로 상품2의 속성값들로 업데이트되있어야함)
findAll() : 상품1, 상품2 생성해서 ItemRepository에 등록, itemReository.findAll() 결과를 리스트에 저장.
리스트의 크기가 상품 갯수와 같은지 비교, 객체 상품1과 상품2를 포함하는지 비교(assertThat(List).contains(item1,item2))