묻고 답해요
141만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결Practical Testing: 실용적인 테스트 가이드
외부API 연동 mocking시 json구조가 복잡하다면 어떻게해야하나요?
학습 관련 질문을 남겨주세요. 어떤 부분이 고민인지, 무엇이 문제인지 상세히 작성하면 더 좋아요!먼저 유사한 질문이 있었는지 검색해 보세요.서로 예의를 지키며 존중하는 문화를 만들어가요. 안녕하세요! 이번 강의 편에서 외부 API mocking에 대해서 다뤄주셔서 감사합니다!궁금한점이 현재 메일을 보내는 sendEmail의 경우 반환타입이 boolean이라 쉽게 테스트가 가능한것 같은데, 만일 RestTemplate/RestClient 와 같이 외부 API 연동한걸 mockito사용해서 가짜 객체로 테스트한다고 했을때, 실제 응답으로 받은 Json의 구조가 복잡할 경우에 어떻게 할지 궁금합니다.thenReturn() 메서드에 해당 응답의 Json구조를 반영한 DTO를 넣어주면 될까 싶었는데, 결국에는 외부 API 응답 구조를 알고 있어야 되는 거라 의존적이라고 생각이 들거든요! 만약 외부 API 응답의 Json 구조가 달라지면 테스트가 깨지게 되는건데, 외부 응답 구조를 몰라야 mocking의 의미가 있는게 아닌지 헷갈립니다.
-
미해결Practical Testing: 실용적인 테스트 가이드
34:40초 부분에서 단축키 어떻게 사용하시나욤
학습 관련 질문을 남겨주세요. 어떤 부분이 고민인지, 무엇이 문제인지 상세히 작성하면 더 좋아요!먼저 유사한 질문이 있었는지 검색해 보세요.서로 예의를 지키며 존중하는 문화를 만들어가요. 안녕하세요! 좋은 강의 감사합니다.영상 중에 34분 쪽에서 타입 이름 변경하실때 왼쪽과 오른쪽 타입의 이름을 동시에 변경하시던데 단축키 어떤거 사용하시는건지 궁금합니당!
-
미해결Practical Testing: 실용적인 테스트 가이드
ApiResponse에 대해 질문있습니다.
학습 관련 질문을 남겨주세요. 어떤 부분이 고민인지, 무엇이 문제인지 상세히 작성하면 더 좋아요!먼저 유사한 질문이 있었는지 검색해 보세요.서로 예의를 지키며 존중하는 문화를 만들어가요. ApiResponse클래스에 HttpStatus와 code를 같이 보내게 되는데 사실 ResponseEntity.ok().body(ApiResponse~~~)이런 식으로 보내게 된다면 httpstatus가 HTTP 메시지의 바디에도 있고 헤더에도 있게 되는데 굳이 바디에 한 번 더 보내시는 이유가 있으신가요??실무에서는 어떻게 하시는 지 궁금합니다.
-
미해결Practical Testing: 실용적인 테스트 가이드
DocsTest와 @WebMvcTest로 만든 테스트를 왜 통합하지 않는지 궁금합니다!!
안녕하세요. 박우빈 강사님. 강의 너무 잘 듣고 있습니다 ㅎㅎㅎ강의를 보고 생각을 하다가 의아하다고 느낀 점이 있어서 질문드립니다.이전에 만든 Controller 테스트와 이번 강의에서 만들었던 DocsTest가 결국 controller를 테스트한다는 점은 동일하고, 문서를 만든다는 개념만 다를 뿐인데, 기능의 중복으로 보이는데 서로 따로 만드는 이유가 있을까요??기존에 Controller 테스트에서 @WebMvcTest를 삭제하고, 필요한 클래스와 mock을 정의한 뒤, API당 하나의 테스트 메서드에만 .andDo(document()를 작성하면 controller 테스트도 수행할 뿐더러 REST Docs를 출력까지 하니 더 좋지 않나 라는 생각이 들었습니다.@WebMvcTest와 이번 강의에서 작성한 DocsTest코드가 .andDo(document()를 이용한 테스트코드내용 출력 기능을 제외하고는 결국 중복된 코드로 보이는데, 기존에 controller test와 DocsTest를 하나로 합쳐서 관리해도 되는 것일까요?요약 : 이번 강의에서 만든 DocsTest로 이전에 만들었던 Controller 테스트를 대체할 수 있을 것으로 보입니다. 실무환경에서는 어떻게 관리되는지 궁금하고, 만약 두개의 테스트코드로 나눠서 관리된다면 굳이 왜 나눴는지가 궁금합니다!!!!우빈 강사님. 강의에서 정말 많이 배워갑니다 감사합니다!!! ㅎㅎㅎㅎ
-
해결됨Practical Testing: 실용적인 테스트 가이드
패키지 구조
학습 관련 질문을 남겨주세요. 어떤 부분이 고민인지, 무엇이 문제인지 상세히 작성하면 더 좋아요!먼저 유사한 질문이 있었는지 검색해 보세요.서로 예의를 지키며 존중하는 문화를 만들어가요. 안녕하세요 강사님 강의를 수강 중 질문이 생겨 질문드립니다.강의 프로젝트의 패키지 구조를 보면 spring 속 api와 domain으로 나누었는데 이는 헥사고날 아케텍쳐와 연관이 있는 건가요??제 생각엔 domain으로만 구별을 해서 한 domain안에 service, controller, entity, repository를 생성했습니다.
-
미해결Practical Testing: 실용적인 테스트 가이드
Dto 사용에 관하여
학습 관련 질문을 남겨주세요. 어떤 부분이 고민인지, 무엇이 문제인지 상세히 작성하면 더 좋아요!먼저 유사한 질문이 있었는지 검색해 보세요.서로 예의를 지키며 존중하는 문화를 만들어가요. 안녕하세요 강사님 강의 코드를 작성중 궁금한 점이 생겨 질문드립니다.강의 예제 코드에서는 Dto를 예를 들어 OrderResponse 이런 식으로 Response, Requset를 생성해서 작성하셨는데 실무에서도 이런 방법으로 하시는 지 궁금합니다.예로 프로젝트가 커지게 된다면 Order에 대해서도 많은 Request, Response가 발생하게 되어 저는 OrderDto 클래스를 두고 OrderDto클래스 속 static inner 클래스로 여러 Dto 클래스를 만들어서 사용했습니다. 이와 같은 방법은 추천 안하시는 지 궁금합니다.또 Dto클래스를 record로 작성하는 경우도 봤는데 record를 사용하는 방법은 어떠한지 궁금합니다.
-
해결됨Practical Testing: 실용적인 테스트 가이드
테스트 대상
학습 관련 질문을 남겨주세요. 어떤 부분이 고민인지, 무엇이 문제인지 상세히 작성하면 더 좋아요!먼저 유사한 질문이 있었는지 검색해 보세요.서로 예의를 지키며 존중하는 문화를 만들어가요. 안녕하세요 강사님강의 13분초 쯤 productType에 대해 test를 하시는데 이 때 HANDMADE와 BAKERY에 대해서만 테스트를 진행하셨는데 BOTTLE에 대해서는 안해도 될까요?? 실무에서는 어떻게 하는 지 궁금합니다. 뭔가 추가해주어야 할 거 같아서요!
-
미해결Practical Testing: 실용적인 테스트 가이드
테스트 나누는 기준
학습 관련 질문을 남겨주세요. 어떤 부분이 고민인지, 무엇이 문제인지 상세히 작성하면 더 좋아요!먼저 유사한 질문이 있었는지 검색해 보세요.서로 예의를 지키며 존중하는 문화를 만들어가요. 안녕하세요 강사님 37분 쯤 test를 주문 생성 시 주문 상태는 INIT이다 라는 test를 하시는데 이를 이전 TotalPrice test하는 testcode와 같이 합쳐서 주문 생성 시 주문 상태는 INIT , TotalPrice를 구할 수 있다 이런식으로 하나로 합치는 건 어떻게 생각하시나요?
-
미해결Practical Testing: 실용적인 테스트 가이드
서비스 레파지토리 의존
학습 관련 질문을 남겨주세요. 어떤 부분이 고민인지, 무엇이 문제인지 상세히 작성하면 더 좋아요!먼저 유사한 질문이 있었는지 검색해 보세요.서로 예의를 지키며 존중하는 문화를 만들어가요. 안녕하세요 강사님 강의를 듣던 중 의문점이 생겨 질문을 남깁니다.강의 28분 쯤 OrderService에서 ProductRepository를 의존하게 되는데 보통 A 레파지토리는 A서비스에서만 의존 하고 B레파지토리를 접근하려면 B서비스를 통해 접근한다 라고 들은 기억이 있는데 혹시 강사님만의 기준이 있을까요??감사합니다.
-
미해결Practical Testing: 실용적인 테스트 가이드
RESTFUL API
학습 관련 질문을 남겨주세요. 어떤 부분이 고민인지, 무엇이 문제인지 상세히 작성하면 더 좋아요!먼저 유사한 질문이 있었는지 검색해 보세요.서로 예의를 지키며 존중하는 문화를 만들어가요. RESTFUL API 방식으로 url 작성 시 강의 13분에 나오는 postmapping에 orders/order이 더 맞지 않나요?? new 보단
-
미해결Practical Testing: 실용적인 테스트 가이드
QueryDsl QueryProjection 을 사용했을 때의 dto 위치
안녕하세요! 덕분에 테스트 코드 잘 짜고있습니다 😋 강사님은 QueryDsl 에서 QueryProjection 을 통해 dto 로 한번에 조회하게 되었을때 해당 dto 를 service 계층에 두시는지, 혹은 repository 계층에 dto 를 하나 더 두시는지 궁금합니다!! 둘다 아니라면 어떻게 하시는지도 궁금합니다! (레이어드 아키텍처를 사용한다고 가정) 만약 Service 단에서 querydsl 을 위한 dto 를 생성하게 되면, repository 계층에서 service 계층을 알게되어 의존성측면에서 좋지 않다고 생각합니다. 그렇다고 repository 계층에서 querydsl 을 위한 dto 를 생성하게되면 의존성측면에서는 괜찮다고 볼 수 있지만 좀 번거롭다고 생각이듭니다. (계층마다 dto 가 하나씩..?) 선생님께서는 어떤 방식으로 해결하시는지가 궁금합니다! 제가 잘못생각한거라면 조언좀 부탁드립니다!(말을 너무 못하네요.. 죄송합니다)
-
미해결Practical Testing: 실용적인 테스트 가이드
테스트 케이스 세분화하기 화면이 안나오는 문제
테스트 케이스 세분화하기에서부터 화면이 안나와요검정 화면으로 자막만 나옵니다.다른 질문을 확인했을 때 크롬 하드웨어 가속을 끄면 나온다고 하여 해당 부분을 수정해서 확인하니 강의는 나오지만, 이부분에 대해 저 또한 문제가 발생하고 있음을 말씀 드립니다! 참고로, 맥북 m1 pro 입니다!
-
미해결Practical Testing: 실용적인 테스트 가이드
TDD질문
학습 관련 질문을 남겨주세요. 어떤 부분이 고민인지, 무엇이 문제인지 상세히 작성하면 더 좋아요!먼저 유사한 질문이 있었는지 검색해 보세요.서로 예의를 지키며 존중하는 문화를 만들어가요. 안녕하세요 강의를 듣던중 의문이 생겨 질문드립니다.TDD 빨간불을 보고 (강의 6분 쯤) 초록불을 만드는 과정에서 return 8500을 하셨는데이렇게 초록불을 만드는 게 맞나요?? 오히려 무슨 테스트를 수정해야하는 지 헷갈릴 거 같은데제가 이해한 초록불을 만드는 과정은 변수명, JPA를 사용한다면 N+1 문제 등 아예 신경안쓰고 초록불을 만들고 위 문제들을 수정해 가는 과정으로 생각했는데..
-
미해결Practical Testing: 실용적인 테스트 가이드
createOrder 변경
학습 관련 질문을 남겨주세요. 어떤 부분이 고민인지, 무엇이 문제인지 상세히 작성하면 더 좋아요!먼저 유사한 질문이 있었는지 검색해 보세요.서로 예의를 지키며 존중하는 문화를 만들어가요. 안녕하세요 강의를 듣다가 의문점이 생겨 질문드립니다.createOrder의 test를 구현하기 위해 LocalTime을 인자로 받게 변경했는데 결국 test를 위해 비지니스 로직을 수정을 하는 과정이 너무 짜치는데 다른 방법은 없을까요? 강의 뒤쪽에 나오는 걸까요?
-
해결됨Practical Testing: 실용적인 테스트 가이드
"테스트 케이스 세분화하기" 강의 화면이 안나옵니다
다른 강의는 잘 나오는데 테스트 케이스 세분화하기 강의만 화면이 까맣게 나옵니다. 저만 그럴까요?Arc 브라우저에서 수강하다가 크롬 브라우저에서도 확인해봤는데 똑같이 화면이 안나옵니다. UPDATE 1: "테스트 케이스 세분화하기" 부터 화면이 안나오는 것 같네요.UPDATE 2: 크롬에서 하드웨어 가속 기능을 끄니까 정상적으로 화면이 나옵니다. 왜 기능을 꺼야하는건지 이유를 알고 싶긴하네요.
-
미해결Practical Testing: 실용적인 테스트 가이드
컨트롤러 테스트 시 POST시 Mockito.when() 처리에서 질문드립니다.
안녕하세요 제가 좀 더 응용해서 post 요청 시에 Mockito.when()과 접목시킨 테스트를 진행해봣는데 이 과정에서 질문이 있어 질문 드립니다. 예시 코드는 다음과 같습니다.void signUpTest() throws Exception { //given var memberResponse = new MemberResponse(MEMBER_ID, MEMBER_EMAIL); var signUpRequest = new SignUpRequest(MEMBER_EMAIL, "password"); //when when(memberFacadeService.signUp(signUpRequest)) .thenReturn(memberResponse); //then mockMvc.perform( post("/api/v1/members/signUp") .content(OBJECT_MAPPER.writeValueAsString(signUpRequest)) .contentType(MediaType.APPLICATION_JSON) ) .andDo(print()) .andExpect(status().isOk()) .andExpect(jsonPath("$.id").value(MEMBER_ID)) .andExpect(jsonPath("$.email").value(MEMBER_EMAIL)); }이 코드 시에 문제가 발생합니다. 문제는 java.lang.AssertionError: No value at JSON path "$.id"이거입니다. 근데, 이 코드를 아래와 같이 바꾸면 에러가 발생하지 않습니다.void signUpTest() throws Exception { //given var memberResponse = new MemberResponse(MEMBER_ID, MEMBER_EMAIL); var signUpRequest = new SignUpRequest(MEMBER_EMAIL, "password"); //when when(memberFacadeService.signUp(any(SignUpRequest.class))) .thenReturn(memberResponse); //then mockMvc.perform( post("/api/v1/members/signUp") .content(objectMapper.writeValueAsString(signUpRequest)) .contentType(MediaType.APPLICATION_JSON) ) .andDo(print()) .andExpect(status().isOk()) .andExpect(jsonPath("$.id").value(MEMBER_ID)) .andExpect(jsonPath("$.email").value(MEMBER_EMAIL)); }위와 아래의 차이는 requestBody에 들어가는 SignUpRequest 클래스를 mockBean처리 된 memberFacadeService의 when 처리 시에 해당 클래스를 any()로 처리하나 안처리하나의 차이입니다. 제가 예상하기에는 mockMvc에서 .content(objectMapper.writeValueAsString(signUpRequest)) 로 이렇게 처리했기 때문에 해당 로직에 들어가는 memberFacadeService 클래스의 signUp 매개변수로 들어가는 SignUpRequest가 제가 위에서 선언한 signUpRequest와 다르기 때문에 발생하는 문제라고 생각합니다. 이 이해가 맞는지에 대한 질문과 post요청에서는 다 이렇게 any()처리를 해야되는지 궁금합니다.
-
미해결Practical Testing: 실용적인 테스트 가이드
테스트할 때 Auditing 없이 원하는 날짜를 설정할 수 잇을까요?
공부삼아서 과제 프로젝트에 테스트를 도입하다가 궁금한 게 잇어서 질문드립니다. 거래내역 조회를 구현할 때 2024-05-30 같은 거래가 발생할 날짜는 auditing, @CreatedAt 통해 저장된 createdAt에서 가져오도록 구현했습니다. (디자인과 달리, 최근 거래일수록 위로 오도록 변경되었습니다) 구현이 끝난 뒤, 테스트할 때 createAt을 임의로 변경하기 위해 BaseEntity의 private를 protected, 그리고 createdAt을 변경하는 메서드를 추가햇습니다. (이게 맞는 접근인지는 잘 모르겟네요... 할 때에도 이렇게 해도 되나? 라는 의문이 계속 들엇습니다...)@DisplayName("유저의 계좌 내역을 불러올 수 있다.") @Test void getUserStatements() { // given (6/5 18:00) LocalDateTime now = LocalDateTime.of(2024, 6, 5, 18, 0, 0); User u1 = User.of("test1", "id1", "pw"); User u2 = User.of("test2", "id2", "pw"); List<User> users = userRepository.saveAll(List.of(u1, u2)); User loginUser = users.get(0); User notLoginUser = users.get(1); Account a1 = Account.of("111-222-3333", 1000, loginUser); Account a2 = Account.of("111-222-3334", 2000, notLoginUser); List<Account> accounts = accountRepository.saveAll(List.of(a1, a2)); Account loginUserAccount = accounts.get(0); Account notLoginUserAccount = accounts.get(1); // 자신 계좌로 입금 (조회 대상), 6/5 발생 Statement s1 = createStatementForTest(loginUserAccount, loginUserAccount, 100, DEPOSIT); // 자신 계좌에서 출금 (조회 대상), 6/6 발생 Statement s2 = createStatementForTest(loginUserAccount, loginUserAccount, 200, WITHDRAW); // 자신 계좌에서 타 계좌로 이체 (조회 대상), 6/7 발생 Statement s3 = createStatementForTest(loginUserAccount, notLoginUserAccount, 300, TRANSFER); // 타 계좌에서 자신 계좌로 이체 (조회 대상), 6/8 발생 Statement s4 = createStatementForTest(notLoginUserAccount, loginUserAccount, 400, TRANSFER); // 타 계좌에서 타 계좌로 출금 (조회 대상 X), 6/9 발생 Statement s5 = createStatementForTest(notLoginUserAccount, notLoginUserAccount, 50000, WITHDRAW); statementRepository.saveAll(List.of(s1, s2, s3, s4, s5)); // when StatementResponse userStatement = statementService.getUserStatements(loginUser); // then assertThat(userStatement.getStatementInfos()).as("거래 이력을 조회할 수 있다.").hasSize(4) .extracting("amount", "type") .containsExactly( tuple(400, "이체"), tuple(-300, "이체"), tuple(-200, "출금"), tuple(100, "입금") ); assertThat(userStatement.getBalance()).as("계좌 잔액을 조회할 수 있다.").isEqualTo(1000); }(위 테스트 코드는 시간 설정 및 검증 코드를 제거한 테스트입니다.) 위 메서드와 plusDays() 통해 시간 설정 후, extracting에 "date" (createdAt에 yyyy-MM-dd를 적용시켜 String 형태로 저장) 를 추가해서 확인했을 때에는 의도한 대로 2024-06-08, 2024-06-07, 2024-06-06, 2024-06-05가 아닌, 전부 테스트를 실행한 시간으로(2024-06-05) 나오는 걸 확인했습니다. 일단은 date를 검증하는 로직을 빼고 테스트를 통과시켰고, postman에서 입금/출금/이체 등 실시 후 조회했을 때에도 의도한 대로 최근 거래가 위로 오도록, 날짜 형식도 의도한 대로 나온 것도 볼 수 있었습니다. 하지만 이 date를 postman이 아닌, auditing 없이 임의로 날짜를 설정한 후 테스트해 확인해보고 싶은데, 이 경우에는 어떻게 하면 될까요? auditing 잇는 상태로도 가능하다면 알려주시면 감사하겟습니다! 아래는 BaseEntity와 거래 내역을 저장하는 Statement Entity 코드입니다@Getter @MappedSuperclass @EntityListeners(AuditingEntityListener.class) public abstract class BaseEntity{ @CreatedDate private LocalDateTime createdDate; }import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; import java.time.LocalDate; import java.time.LocalDateTime; import static jakarta.persistence.EnumType.*; @Entity @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) public class Statement extends BaseEntity{ @Id @GeneratedValue(strategy= GenerationType.IDENTITY) private Long id; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name="from_account") private Account from; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name="to_account") private Account to; private int amount; @Enumerated(STRING) private TransactionType type; @Builder private Statement(Account from, Account to, int amount, transactionType type) { this.from = from; this.to = to; this.amount = amount; this.type = type; } public static Statement of(Account from, Account to, int amount, transactionType type){ return Statement.builder() .from(from) .to(to) .amount(amount) .type(type) .build(); } } 긴 글 읽어주셔서 감사합니다~
-
해결됨Practical Testing: 실용적인 테스트 가이드
jpaRepository 에서 update 메서드 테스트 질문 드립니다.
jpaRepository에서 update 관련 메서드를 테스트하던 중 고민이 생겼습니다.update로 변경한 결과가 DB가 아닌, 영속성 컨텍스트에만 반영이 되어서 수정된 값을 확인하기 위해 find()메서드로 저장된 객체를 불러오면 수정한 것과 다른 원본 결과가 출력됩니다.이 문제를 해결하기 위해 두 가지 방법을 생각해보았습니다.하나는 @Modifying 애노테이션에 clearAutomatically = true 라는 옵션을 달아주는 방법이었는데, 이 방식은 테스트를 위해 프로덕션 코드를 수정하기도 하고 성능에 문제가 발생해서 제외하였고다른 하나는 테스트 코드에 EntityManager를 이용해 강제로 flush()와 clear()를 이용해 영속성 컨텍스트를 비워주도록 하는 방법이었습니다. 이 방식도 테스트 코드가 깔끔하지 않고 더 jpa에 종속적이게 되는 것 같아서 마음에 들진 않는데 강사님은 어떤 방식으로 해결하셨는지 궁금합니다!
-
미해결Practical Testing: 실용적인 테스트 가이드
access token의 경우 테스트 코드에서 어떻게 처리해야되나요?
안녕하세요. 현재 강의 잘 수강하고 있습니다.현재 거의 모든 controller에서 access token을 받아서 사용하고 있습니다.토큰의 경우 만료시간 등이 있는데 테스트 코드에서 어떻게 처리되는지 궁금합니다.저 같은 경우는 spring security 사용하지 않고, 직접 API로 Token을 발급하였습니다.예시라던지 레퍼런스가 있다면 공유 좀 부탁드려요~감사합니다.
-
미해결Practical Testing: 실용적인 테스트 가이드
a 서비스에서 b 서비스를 의존하는 코드에 대한 테스트는 어떻게 해야 되나요??
안녕하세요 강사님, 궁금한게있습니다.인스타그램, 페이스북을 사용할 때 제가 쓴 게시글에 다른 사람이 댓글을 달면 알림이 생성되는데, 제가 작성한 로직에서는 CommentService에서 댓글을 작성하고 alarmService를 호출하여 알림까지 생성하는 로직입니다.이렇게 로직을 짰을 때 제가 생각한 문제점에 대한 해답을 찾고 싶습니다.1. CommentService에서 다른 Service를 의존하게 되는 것2. 댓글 작성이라는 테스트를 짤 때 댓글 작성에 초첨을 맞출 수 없고 알림까지 테스트를 작성해야 되기 떄문에 핵심 기능 외에 다른 부가적인 기능 때문에 테스트의 집중도가 떨어집니다.3. 한 트랙잭션에 묶여서 알림을 생성하는데 문제가 발생하면 댓글도 생성되지 않습니다.이러한 경우 어떤 학습을 통해 개선할 수 있는지 가르쳐주실 수 있나요?