1. 다양한 테스트 Edge 케이스 고려
1-1) 회원Id
- 회원 아이디 (userId) 가 null 로 들어온다면, 등록된 상품은 어떤 회원의 상품이 되는거지?
- 회원 아이디 (userId) 가 마이너스 값이라면, 등록된 상품은 어떤 회원의 상품이 되는거지? (DB 테이블 Id 의 경우 마이너스 값을 갖지 않음)
1-2) 상품명
- 상품명이 null 로 들어오면 어떻하지?
- 상품명이 빈 문자열인 경우에도 저장을 해야 할까? (UI 에는 어떻게 표시될까?)
1-3) 상품 이미지 URL
- 상품 이미지 URL 이 null 로 들어오면?
- 상품 이미지 URL 이 URL 형태가 아니라면?? (UI 에는 어떻게 표시될까?)
1-4) 상품 최저가 페이지 URL
- 상품 최저가 페이지 URL 이 null 로 들어오면?
- 상품 최저가 페이지 URL 이 URL 형태가 아니라면?? (UI 에는 어떻게 표시될까?)
1-5) 상품 최저가
- 상품 최저가가 0 이라면? (공짜 상품??)
- 상품 최저가가 음수라면??
2. Edge 케이스 발견 후 처리방법
Edge 케이스에 대해 개발자가 독단적으로 방향을 결정하는 것보다는, 관련 담당자(들)과 협의 진행 후 결정합니다.
- 관련 담당자: 개발팀 선배, 기획자, 디자이너, QA
- 예를들면,
- 빈 문자열 허용 → UI 에 빈 문자열 그대로 표시?
- 빈 이미지 허용 → UI 에 대체 이미지 표시?
- 에러 발생 시켜야 한다면, 고객이 이해할 수 있는 정확한 에러문구 필요
상황별 대응 방향성이 결정 되었다면 이를 코드에 반영.
# Product 클래스
// 관심 상품 생성 시 이용합니다.
public Product(ProductRequestDto requestDto, Long userId) {
// 입력값 Validation
if (userId == null || userId < 0) {
throw new IllegalArgumentException("회원 Id 가 유효하지 않습니다.");
}
if (requestDto.getTitle() == null || requestDto.getTitle().isEmpty()) {
throw new IllegalArgumentException("저장할 수 있는 상품명이 없습니다.");
}
if (!URLValidator.urlValidator(requestDto.getImage())) {
throw new IllegalArgumentException("상품 이미지 URL 포맷이 맞지 않습니다.");
}
if (!URLValidator.urlValidator(requestDto.getLink())) {
throw new IllegalArgumentException("상품 최저가 페이지 URL 포맷이 맞지 않습니다.");
}
if (requestDto.getLprice() <= 0) {
throw new IllegalArgumentException("상품 최저가가 0 이하입니다.");
}
// 관심상품을 등록한 회원 Id 저장
this.userId = userId;
this.title = requestDto.getTitle();
this.image = requestDto.getImage();
this.link = requestDto.getLink();
this.lprice = requestDto.getLprice();
this.myprice = 0;
}
util > URLValidator
public class URLValidator {
public static boolean urlValidator(String url) {
try {
new URL(url).toURI();
return true;
}
catch (URISyntaxException exception) {
return false;
}
catch (MalformedURLException exception) {
return false;
}
}
}
반영한 코드 테스트
class ProductTest {
@Nested //테스트 결과 폴더 구조화
@DisplayName("회원이 요청한 관심상품 객체 생성") //테스트 결과 표시 이름
class CreateUserProduct {
private Long userId;
private String title;
private String image;
private String link;
private int lprice;
@BeforeEach // 테스트에서 공통 부분
void setup() {
userId = 100L;
title = "오리온 꼬북칩 초코츄러스맛 160g";
image = "https://shopping-phinf.pstatic.net/main_2416122/24161228524.20200915151118.jpg";
link = "https://search.shopping.naver.com/gate.nhn?id=24161228524";
lprice = 2350;
}
@Test
@DisplayName("정상 케이스")
void createProduct_Normal() {
// given
ProductRequestDto requestDto = new ProductRequestDto(title, image, link, lprice);
// when
Product product = new Product(requestDto, userId);
// then
assertNull(product.getId());
assertEquals(userId, product.getUserId());
assertEquals(title, product.getTitle());
assertEquals(image, product.getImage());
assertEquals(link, product.getLink());
assertEquals(lprice, product.getLprice());
assertEquals(0, product.getMyprice());
}
@Nested
@DisplayName("실패 케이스")
class FailCases {
@Nested
@DisplayName("회원 Id")
class userId {
@Test
@DisplayName("null")
void fail1() {
// given
userId = null;
ProductRequestDto requestDto = new ProductRequestDto(title, image, link, lprice);
// when
Exception exception = assertThrows(IllegalArgumentException.class, () -> {
new Product(requestDto, userId);
});
// then
assertEquals("회원 Id 가 유효하지 않습니다.", exception.getMessage());
}
@Test
@DisplayName("마이너스")
void fail2() {
// given
userId = -100L;
ProductRequestDto requestDto = new ProductRequestDto(title, image, link, lprice);
// when
Exception exception = assertThrows(IllegalArgumentException.class, () -> {
new Product(requestDto, userId);
});
// then
assertEquals("회원 Id 가 유효하지 않습니다.", exception.getMessage());
}
}
@Nested
@DisplayName("상품명")
class Title {
@Test
@DisplayName("null")
void fail1() {
// given
title = null;
ProductRequestDto requestDto = new ProductRequestDto(title, image, link, lprice);
// when
Exception exception = assertThrows(IllegalArgumentException.class, () -> {
new Product(requestDto, userId);
});
// then
assertEquals("저장할 수 있는 상품명이 없습니다.", exception.getMessage());
}
@Test
@DisplayName("빈 문자열")
void fail2() {
// given
String title = "";
ProductRequestDto requestDto = new ProductRequestDto(title, image, link, lprice);
// when
Exception exception = assertThrows(IllegalArgumentException.class, () -> {
new Product(requestDto, userId);
});
// then
assertEquals("저장할 수 있는 상품명이 없습니다.", exception.getMessage());
}
}
@Nested
@DisplayName("상품 이미지 URL")
class Image {
@Test
@DisplayName("null")
void fail1() {
// given
image = null;
ProductRequestDto requestDto = new ProductRequestDto(title, image, link, lprice);
// when
Exception exception = assertThrows(IllegalArgumentException.class, () -> {
new Product(requestDto, userId);
});
// then
assertEquals("상품 이미지 URL 포맷이 맞지 않습니다.", exception.getMessage());
}
@Test
@DisplayName("URL 포맷 형태가 맞지 않음")
void fail2() {
// given
image = "shopping-phinf.pstatic.net/main_2416122/24161228524.20200915151118.jpg";
ProductRequestDto requestDto = new ProductRequestDto(title, image, link, lprice);
// when
Exception exception = assertThrows(IllegalArgumentException.class, () -> {
new Product(requestDto, userId);
});
// then
assertEquals("상품 이미지 URL 포맷이 맞지 않습니다.", exception.getMessage());
}
}
@Nested
@DisplayName("상품 최저가 페이지 URL")
class Link {
@Test
@DisplayName("null")
void fail1() {
// given
link = "https";
ProductRequestDto requestDto = new ProductRequestDto(title, image, link, lprice);
// when
Exception exception = assertThrows(IllegalArgumentException.class, () -> {
new Product(requestDto, userId);
});
// then
assertEquals("상품 최저가 페이지 URL 포맷이 맞지 않습니다.", exception.getMessage());
}
@Test
@DisplayName("URL 포맷 형태가 맞지 않음")
void fail2() {
// given
link = "https";
ProductRequestDto requestDto = new ProductRequestDto(title, image, link, lprice);
// when
Exception exception = assertThrows(IllegalArgumentException.class, () -> {
new Product(requestDto, userId);
});
// then
assertEquals("상품 최저가 페이지 URL 포맷이 맞지 않습니다.", exception.getMessage());
}
}
@Nested
@DisplayName("상품 최저가")
class LowPrice {
@Test
@DisplayName("0")
void fail1() {
// given
lprice = 0;
ProductRequestDto requestDto = new ProductRequestDto(title, image, link, lprice);
// when
Exception exception = assertThrows(IllegalArgumentException.class, () -> {
new Product(requestDto, userId);
});
// then
assertEquals("상품 최저가가 0 이하입니다.", exception.getMessage());
}
@Test
@DisplayName("음수")
void fail2() {
// given
lprice = -1500;
ProductRequestDto requestDto = new ProductRequestDto(title, image, link, lprice);
// when
Exception exception = assertThrows(IllegalArgumentException.class, () -> {
new Product(requestDto, userId);
});
// then
assertEquals("상품 최저가가 0 이하입니다.", exception.getMessage());
}
}
}
}
}
'프로그래밍 > SpringBoot' 카테고리의 다른 글
Spring Data JPA (0) | 2022.06.08 |
---|---|
통합 테스트(Integration Test) - 예제) 관심상품 통합 테스트 (0) | 2022.06.06 |
JUnit 테스트란? (0) | 2022.06.06 |
카카오 로그인 구현(2) (0) | 2022.06.03 |
카카오 로그인 구현(1) - 사전 설정 (0) | 2022.06.02 |