묻고 답해요
141만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결Practical Testing: 실용적인 테스트 가이드
현재 시간에 의존하는 코드
학습 관련 질문을 남겨주세요. 어떤 부분이 고민인지, 무엇이 문제인지 상세히 작성하면 더 좋아요!먼저 유사한 질문이 있었는지 검색해 보세요.서로 예의를 지키며 존중하는 문화를 만들어가요. 안녕하세요. 테스트 강의를 보고 실천(?)하고 있는 개발자입니다!최근 현재 시간에 대한 테스트를 짜던 도중, 현재 시간을 모킹하는 방법이 있다는 걸 알게 됐습니다. 우빈님 강의에서는 현재시간을 파라미터로 받는 방식을 통해 테스트를 짜셨는데, 두 가지 방법에 대해 어떻게 생각하시는지 의견이 궁금합니다!
-
미해결Practical Testing: 실용적인 테스트 가이드
OrderRepositoryTest에서 발생한 에러
package sample.cafekiosk.spring.domain.order; @ActiveProfiles("test") @DataJpaTest class OrderRepositoryTest { @Autowired private OrderRepository orderRepository; @Autowired private ProductRepository productRepository; @DisplayName("특정 주문 상태에 따라 주문을 조회한다") @Test void findOrdersBy() { //given Product product1 = createProduct("아메리카노", 3000, HANDMADE, SELLING); Product product2 = createProduct("카페라떼", 4000, HANDMADE, SELLING); Product product3 = createProduct("카푸치노", 5000, HANDMADE, SELLING); List<Product> products = List.of(product1, product2, product3); LocalDateTime startTime = LocalDateTime.of(2023, 10, 19, 0, 0); LocalDateTime orderTime = LocalDateTime.of(2023, 10, 19, 10, 0); LocalDateTime endTime = LocalDateTime.of(2023, 10, 20, 0, 0); Order completedOrder = createOrder(orderTime, PAYMENT_COMPLETED, products); Order canceledOrder = createOrder(orderTime, CANCELED, products); // when List<Order> orders = orderRepository.findOrdersBy(startTime, endTime, PAYMENT_COMPLETED); // then assertThat(orders).hasSize(1) .extracting("id", "orderStatus", "totalPrice", "registeredDateTime") .containsExactlyInAnyOrder( tuple(1L, PAYMENT_COMPLETED, 12000, orderTime) ); } private Product createProduct(String name, int price, ProductType productType, ProductSellingStatus productSellingStatus) { Product product = Product.builder() .name(name) .price(price) .type(productType) .sellingStatus(productSellingStatus) .build(); return productRepository.save(product); } private Order createOrder(LocalDateTime now, OrderStatus orderStatus, List<Product> products) { Order order = Order.builder() .products(products) .orderStatus(orderStatus) .registeredDateTime(now) .build(); return orderRepository.save(order); } @DisplayName("찾고자 하는 시간 안에 있는 주문을 조회한다") @Test void findOrdersBy2() { //given Product product1 = createProduct("아메리카노", 3000, HANDMADE, SELLING); Product product2 = createProduct("카페라떼", 4000, HANDMADE, SELLING); Product product3 = createProduct("카푸치노", 5000, HANDMADE, SELLING); List<Product> products = List.of(product1, product2, product3); LocalDateTime startTime = LocalDateTime.of(2023, 10, 19, 0, 0); LocalDateTime orderTime = LocalDateTime.of(2023, 10, 19, 10, 0); LocalDateTime endTime = LocalDateTime.of(2023, 10, 20, 0, 0); LocalDateTime overTime = LocalDateTime.of(2023, 10, 20, 10, 0); Order completedOrder = createOrder(orderTime, PAYMENT_COMPLETED, products); Order overTimeOrder = createOrder(overTime, PAYMENT_COMPLETED, products); // when List<Order> orders = orderRepository.findOrdersBy(startTime, endTime, PAYMENT_COMPLETED); // then assertThat(orders).hasSize(1) .extracting("id", "orderStatus", "totalPrice", "registeredDateTime") .containsExactlyInAnyOrder( tuple(1L, PAYMENT_COMPLETED, 12000, orderTime) ); } }각각 Test 수행할 땐 정상적으로 잘 동작했습니다. 하지만, 같이 Test을 수행하는 경우 findOrdersBy()에서 아래와 같은 에러가 발생하고 있습니다2023-10-20 23:12:40.519 INFO 8704 --- [ main] o.s.t.c.transaction.TransactionContext : Began transaction (1) for test context [DefaultTestContext@1a6c1270 testClass = OrderRepositoryTest, testInstance = sample.cafekiosk.spring.domain.order.OrderRepositoryTest@2d114d27, testMethod = findOrdersBy@OrderRepositoryTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@18a136ac testClass = OrderRepositoryTest, locations = '{}', classes = '{class sample.cafekiosk.spring.CafeKioskApplication}', contextInitializerClasses = '[]', activeProfiles = '{test}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.autoconfigure.OverrideAutoConfigurationContextCustomizerFactory$DisableAutoConfigurationContextCustomizer@560348e6, org.springframework.boot.test.autoconfigure.actuate.metrics.MetricsExportContextCustomizerFactory$DisableMetricExportContextCustomizer@6f1c29b7, org.springframework.boot.test.autoconfigure.filter.TypeExcludeFiltersContextCustomizer@351584c0, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@fb58afcf, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@7b7fdc8, [ImportsContextCustomizer@77d67cf3 key = [org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration, eJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@27d5a580, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.context.SpringBootTestArgs@1, org.springframework.boot.test.context.SpringBootTestWebEnvironment@0], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.event.ApplicationEventsTestExecutionListener.recordApplicationEvents' -> false]]; transaction manager [org.springframework.orm.jpa.JpaTransactionManager@40d10264]; rollback [true] Hibernate: insert into product (id, created_date_time, modified_date_time, name, price, product_number, selling_status, type) values (default, ?, ?, ?, ?, ?, ?, ?) Hibernate: insert into product (id, created_date_time, modified_date_time, name, price, product_number, selling_status, type) values (default, ?, ?, ?, ?, ?, ?, ?) Hibernate: insert into product (id, created_date_time, modified_date_time, name, price, product_number, selling_status, type) values (default, ?, ?, ?, ?, ?, ?, ?) Hibernate: insert into orders (id, created_date_time, modified_date_time, order_status, registered_date_time, total_price) values (default, ?, ?, ?, ?, ?) Hibernate: insert into order_product (id, created_date_time, modified_date_time, order_id, product_id) values (default, ?, ?, ?, ?) Hibernate: insert into order_product (id, created_date_time, modified_date_time, order_id, product_id) values (default, ?, ?, ?, ?) Hibernate: insert into order_product (id, created_date_time, modified_date_time, order_id, product_id) values (default, ?, ?, ?, ?) Hibernate: insert into orders (id, created_date_time, modified_date_time, order_status, registered_date_time, total_price) values (default, ?, ?, ?, ?, ?) Hibernate: insert into order_product (id, created_date_time, modified_date_time, order_id, product_id) values (default, ?, ?, ?, ?) Hibernate: insert into order_product (id, created_date_time, modified_date_time, order_id, product_id) values (default, ?, ?, ?, ?) Hibernate: insert into order_product (id, created_date_time, modified_date_time, order_id, product_id) values (default, ?, ?, ?, ?) Hibernate: select order0_.id as id1_2_, order0_.created_date_time as created_2_2_, order0_.modified_date_time as modified3_2_, order0_.order_status as order_st4_2_, order0_.registered_date_time as register5_2_, order0_.total_price as total_pr6_2_ from orders order0_ where order0_.registered_date_time>=? and order0_.registered_date_time<? and order0_.order_status=? 2023-10-20 23:12:40.621 INFO 8704 --- [ main] o.s.t.c.transaction.TransactionContext : Rolled back transaction for test: [DefaultTestContext@1a6c1270 testClass = OrderRepositoryTest, testInstance = sample.cafekiosk.spring.domain.order.OrderRepositoryTest@2d114d27, testMethod = findOrdersBy@OrderRepositoryTest, testException = java.lang.AssertionError: [Extracted: id, orderStatus, totalPrice, registeredDateTime] Expecting actual: [(3L, PAYMENT_COMPLETED, 12000, 2023-10-19T10:00 (java.time.LocalDateTime))] to contain exactly in any order: [(1L, PAYMENT_COMPLETED, 12000, 2023-10-19T10:00 (java.time.LocalDateTime))] elements not found: [(1L, PAYMENT_COMPLETED, 12000, 2023-10-19T10:00 (java.time.LocalDateTime))] and elements not expected: [(3L, PAYMENT_COMPLETED, 12000, 2023-10-19T10:00 (java.time.LocalDateTime))] , mergedContextConfiguration = [MergedContextConfiguration@18a136ac testClass = OrderRepositoryTest, locations = '{}', classes = '{class sample.cafekiosk.spring.CafeKioskApplication}', contextInitializerClasses = '[]', activeProfiles = '{test}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTestContextBootstrapper=true}', contextCustomizers = 왜 id가 3인가요?? 저는 DataJpaTest을 수행하면 각각의 Test 마다 rollBack이 수행되어 id가 당연히 1이라고 생각했었습니다. 왜 3이 되는지 이해가 되지 않습니다
-
미해결Practical Testing: 실용적인 테스트 가이드
정적 팩터리 메서드 사용 기준?
제목 그대로 언제 사용하시는지에 대해 얘기를 나눠보고 싶어 질문 남깁니다.제 경우는 영속성 계층에 새로운 객체가 추가될 때 (RDB에 레코드를 추가할 때) new 키워드를 사용하여 id 값을 생성자로 받지 않는 생성자를 열어두고,존재하는 도메인 엔티티 혹은 영속성 엔티티를 영속성 계층으로부터 불러올 때는 정적 팩터리 메서드를 사용하는데강의를 진행하시면서 습관적으로 생성자 대신 static 메서드를 통해 생성 하시더라구요, 강사님만의 명확한 기준이 있으신지 궁금합니다.
-
미해결Practical Testing: 실용적인 테스트 가이드
ProductRepository에 @Repository 어노테이션을 붙인 이유
스프링 컨테이너가 뜰 때 Jpa의 Repository 인터페이스 하위 타입을 스캔하여 빈으로 등록하는 것으로 알고 있어서 ProductRepository가 자동으로 스캔이 될텐데 @Repository 어노테이션을 붙이신 이유가 궁금합니다
-
미해결Practical Testing: 실용적인 테스트 가이드
ProductNumberFactory 클래스는 어떤 Layer 객체로 봐야 할까요?
안녕하세요! 먼저 항상 좋은 강의 감사드립니다! 저도 작은 경험 이지만 개발을 하면서 서비스 단의 로직을 분리 (강의에서 말씀 해주신 것 처럼 책임을 분리할 정도)해야 하는 상황인 경우, 이렇게 하는게 맞는지는 모르겠으나, Point1. ServiceUtil 클래스를 정의하여 컴포넌트로 주입받아 사용하거나 (실무에선 이렇게 사용)Point2. 학습시에는 Facade 패턴을 이용하여 서로 다른 서비스들의 상위 퍼사드 객체를 만들어서 사용한 적이 있습니다.(물론 퍼사드 패턴의 경우, 두 로직이 완전히 다른 맥락인 경우에 사용하는 것 같습니다.. 강의 예제와 같이 결합도가 높은 경우가 아니라..)그런데, 강의에서는 Factory 객체를 만들어서 (마치 제가 ServiceUtil을 만들어서 사용하는 것 처럼 - 사실 이름만 다르지 같습니다)사용하시는 모습을 보여주셨는데, Q1. 강사님께서는 실무에서 서비스의 책임을 분리할 때 주로 이런식으로 Factory 클래스를 분리하여 사용하시는지 궁금하고, Q2.그렇게 Factory 클래스로 책임을 분리했을 때, 이 Factory 클래스는 Controller / Service/ Repository 그 어느것도 아니게 되는데, Spring WEB mvc 레이어 아키텍쳐 상으로 어떤 Layer의 어떤 입장의 객체로 인지하고 사용해야 하는지 여쭙고 싶습니다. 감사합니다.
-
미해결Practical Testing: 실용적인 테스트 가이드
private method 테스트문의
안녕하세요. 좋은 강의 잘 듣고 있습니다 ^^ 강의에서 private method 테스트를 해야되는 상황이라면객체를 분리해야되는 상황이라고 말씀을 주셨는데실무에서는 꼭 분리를 해야되는 상황이 아닐수도 있을텐데1)실무에서는 private method 에 대한 테스트는 거의 작성안하나요? 2)레거시 프로젝트를 맡았을때 public method 에 대한 테스트를 작성하기에는 많은 작업이 필요하다면 private method 라도 테스트 코드를 작성하는게 좋을거 같은데 이런 경우도 작성을 안하나요?3) private 함수를 변경하는경우 해당함수만 테스트하고 싶을거 같은데 이런경우는 어떻게하나요?
-
미해결Practical Testing: 실용적인 테스트 가이드
controller, service dto 분리에대해 질문드립니다.
포스, 키오스크, 이외 다른 주문 엔드포인트로부터 주문이 들어왔을때 똑같은 서비스를 사용할 경우 그 서비스에서 사용하는 서비스dto로 변환해주어야 하기 때문에 컨트롤러 dto와 서비스dto를 분리해주는게 좋다로 이해했는데 맞을까요?
-
해결됨Practical Testing: 실용적인 테스트 가이드
생성 post 요청 시 Response 객체 전달 이유
Order를 생성하면서 이에 대한 서비스 반환 값으로 orderResponse를 반환하는 것을 볼 수 있었습니다.얕은 지식으로는 Create에 해당하는 내용은 201 상태코드와 URI.Created 를 사용하여 헤더에 Location을 명시해주고 "/api/v1/orders/" + id형태로 제공해주는 것이 좋은 것으로 알고 있었는데 생성 시에도 반환 값을 제공해주시는 이유가 있을까요?
-
해결됨Practical Testing: 실용적인 테스트 가이드
Beverage 인터페이스
테스트의 질문과는 좀 벗어나는 질문입니다만.. 궁금해서 여쭤보게 되었습니다!간단한 프로젝트를 구성하는 과정에서 Beverage라는 인터페이스를 만들어 추상화를 진행하고 해당 인터페이스는 get의 행위만 가지고 있었습니다.그리고 추가된 라떼와 아메리카노 둘 다 같은 속성이지만 구현을 통해서 두 개의 구성 클래스를 만들어 예제를 진행하였는데요.이에 다음과 같은 의문점이 생겼습니다.인터페이스가 get이라는 행위만 가져도 사용해도 괜찮은지. 지금과 같은 상황에서는 확장에서의 의미로 추상 클래스가 더 괜찮을 것 같은데 사용하지 않은 이유가 있으신지 궁금합니다ㅎㅎ좋은 강의 제공해주셔서 감사합니다~
-
미해결Practical Testing: 실용적인 테스트 가이드
Repository 구현시 @Repository 어노테이션을 붙이는 이유가 궁금합니다.
안녕하세요, 우빈님 너무 좋은 강의를 올려주셔서 잘 듣고 있습니다! Repository 구현 시 @Repository 어노테이션을 붙이는 이유가 궁금합니다.스프링 데이터 JPA를 사용할 경우 스프링이 만들어서 제공하는 컴포넌트를 사용해서 @Repository 를 생략해도 되는 거로 알고 있는데, 사용하시는 이유가 따로 있는지 궁금합니다.
-
해결됨Practical Testing: 실용적인 테스트 가이드
내부적으로 orderProduct생기는 이유
학습 관련 질문을 남겨주세요. 어떤 부분이 고민인지, 무엇이 문제인지 상세히 작성하면 더 좋아요!먼저 유사한 질문이 있었는지 검색해 보세요.서로 예의를 지키며 존중하는 문화를 만들어가요. [공지] 제가 9/27 ~ 10/9 약 2주간 해외 여행을 가게 되어, 해당 기간 동안은 질문에 대한 답변이 불가합니다. 🥲 질문을 남겨주시면 10/10 이후로 순차적으로 확인하고 빠르게 답변드릴 수 있도록 하겠습니다. 너른 양해 부탁드리며, 강의를 수강해주시는 분들 모두 항상 감사드리고, 또 응원합니다. 🙌🏻 다시 코드를 보니 헷갈리는게 있어서 질문 드립니다!OrderService에서 createOrder를 할때 내부적으로 중간 매핑 엔티티인 OrderProduct가 생기는 이유가 Order엔티티에 있는 create메서드를 호출 빌더로 Order객체를 생성할때 orderProducts리스트 초기화orderProducts는 casecade = CasecadeType.ALL이 되어있으므로 2번 과정으로 인하여 객체가 생성되고 db에 저장이 맞을까요? 감사합니다!
-
해결됨Practical Testing: 실용적인 테스트 가이드
Mock Test에 관련한 질문
학습 관련 질문을 남겨주세요. 어떤 부분이 고민인지, 무엇이 문제인지 상세히 작성하면 더 좋아요!먼저 유사한 질문이 있었는지 검색해 보세요.서로 예의를 지키며 존중하는 문화를 만들어가요. [공지] 제가 9/27 ~ 10/9 약 2주간 해외 여행을 가게 되어, 해당 기간 동안은 질문에 대한 답변이 불가합니다. 🥲 질문을 남겨주시면 10/10 이후로 순차적으로 확인하고 빠르게 답변드릴 수 있도록 하겠습니다. 너른 양해 부탁드리며, 강의를 수강해주시는 분들 모두 항상 감사드리고, 또 응원합니다. 🙌🏻 안녕하세요 우빈님! 강의 수강 중 궁금한 점이 생겨서 질문드립니다!지금까지 작성한 테스트들은 Production Code가 제대로 동작하기 위해서 ~~했을때 이러한 결과가 나와야한다! 식의 검증을 제대로 한다는 느낌을 받았습니다. 그래서 후에 코드를 수정하고 테스트를 다시 돌려보며 로직이 제대로 실행하는지를 검증하며 테스트의 이점을 잘 활용할 수 있겠다라고 생각하였습니다. 하지만 Mock에 대해 학습을 하면서는 이 테스트가 효과적인 테스트인가? 하는 의문이 조금씩 들기 시작하였습니다.물론 지난 시간 학습하였던 OrderStatisticsService 의 경우 테스트의 주된 목적은 총 금액 확인이었으므로 sendEmail 메서드의 Stubbing은 왜 하는지 이해하였습니다. 이번 강의를 들으면서 몇가지 의문점이 생겼는데 다음과 같습니다!sendEmail을 Stubbing하면 당연히 반환되는 값은 Ture 일 것Mock객체의 defaultAnswer에 의해서 mailSendHistoryRepository.save()의 반환값이 null이어도 테스트가 성공함로직을 원하는대로 수행하기 위해 메서드가 몇번 호출되는지 검증을 할 필요가 있는가? 전체적으로 Stubbing을 얼마나 잘하는지에 대한 테스트를 한다는 느낌을 받았습니다!혹시 기능에 대한 사용법을 알려주시려고 한것인지 아니면 실무에서도 이러한 테스트를 작성하는지, 작성한다면 verify()를 사용할때 메서드 호출횟수를 검증하여 얻고자 하는것은 무엇인지, 그리고 모든 메서드를 Sutbbing하게 되면 해당 코드에서 무엇을 검증하는것인지 궁금합니다! 감사합니다!
-
미해결Practical Testing: 실용적인 테스트 가이드
Controller와 Service간의 requestDto를 구분하는 측면
충분히 공감가고 이해되는 내용입니다! 좋은 내용 설명해주셔서 감사합니다!그렇다면 responseDto도 순수 서비스 응답과 ,각 컨트롤러 별 응답으로 구분하는게 좋을까요?
-
미해결Practical Testing: 실용적인 테스트 가이드
ApiResponse에 HttpStatus를 설정하는것의 의미 관련 질문
안녕하십니까! 항상 좋은 강의 감사드립니다.ApiResponse에 HttpStatus를 필드로 두어,응답 상황에 따라 적절한 HttpStatus를 설정하도록 강의에서 의도해주셨습니다.실제로 저도 이런식으로 사용하고 있었는데요,그런데 이번에 테스트 하면서 알게 된 것이지만,ApiResponse에 HttpStatus를 넣어준다고 하더라도실제 응답 HTTP의 status에는 반영이 되지 않고,단순히 응답 body에만 설정한 status가 쓰여졌습니다.아래 첨부한 사진을 보면 201로 setting 하였지만,실제 응답은 200 인걸 예로 확인할 수 있었습니다.그래서 제가 질문 드리고 싶은 부분은,"그렇다면 응답을 어떻게 해야 하는가?" 입니다.ApiResponse라는 공통 응답을 한번 더 ResponseEntity<> 안에 감싸서 보내는 방법을 생각해 볼 수 있을 것 같습니다.단 이방식은 ApiResponse의 status를 ResponseEntity의 status로 동기화 시켜주는 작업과,그리고 응답 타입도 ResponseEntity<ApiResponse<>>이런식으로 depth가 2번 생기게 되는 단점이 있을 것 같습니다.(depth가 2번 생긴다는게 올바른 표현인지는 모르겠으나,서비스 응답을 ApiResponse로 한번 감쌌는데,이를 한번 더 ResponseEntity로 감싼 것을 2번의 depth로 표현하였습니다.)두 번째로는 오직 응답 바디에 있는 값 만을 사용하기로 프론트와 규약을 정하고 사용하는 방법이 있을 것 같습니다.이렇게 하면 굳이 한번 더 ResponseEntity<>로 감쌀 수고는 덜어질 것 같습니다. 제가 생각한 방식은 이렇게 두가지가 있을 것 같고, 제가 속한 회사에서 기존 방식은 2번째 방식을 사용하고 있었습니다.그런데 , 저는 신규 프로젝트에 투입되어 있는 상황 이여서 코드를 제가 원하는 대로? 짤 수 있는 상황인데요,,그래서 위 두가지 방식중에 어떤것이 좋을지,혹은 더 나은 방식이 있을지 질문 드리고 싶습니다.제가 3개월 차라 .. 경험이 많이 부족해서,,강사님 경험에 기반하여 답변해주시면 정말 감사하겠습니다.
-
미해결Practical Testing: 실용적인 테스트 가이드
ProductNumber 계산 로직
안녕하십니까! 먼저 항상 좋은 강의 감사드립니다.특히 이번 강의에서는 Transaction에서 readOnly 옵션을 사용하므로써 JPA 최적화를 통해 성능 향상을 이점을 얻을 수 있다와 함께,CQRS 측면을 말씀해 주셔서 좋았습니다!저의 경우는 아직 master/slave DB 구조를 다뤄본적이 없어서 몰랐는데, 이렇게 readOnly 옵션을 사용할 경우 DB endpoint를 구분하여 명시하므로써 master/slave DB 구조를 사용할 수 있다는 측면도 알게되어서 좋았습니다.본론으로 넘어가서, Q1. ProductNumber를 계산하는 로직을 DB에서 최신값을 읽어온 후에 ,그 값을 기반으로 다음 productNumber 값을 계산하는 로직을 저의 경우는 동시성 이슈를 고려하여 , 1.일단 SaveAndFlush()로 Id를 할당받고 2. 그 Id 값으로 만들자 라는 로직을 사용하였습니다.(IDENTITY 전략이므로 테이블당 1부터 Id가 할당되기 때문에 가능)이러한 저의 로직에 문제가 있는지 피드백 주시면 정말 감사하겠습니다.특히 calculateProductNumber() 메소드를 저의 경우는 도메인 주도 전략에 기반하여 서비스의 private Method로 정의하지 않고 , Entity 안에 정의하여 사용하는 편인데, 이러한 스타일에 대해서도 문제가 없을지 여쭤보고 싶습니다.Q2.두번째로 저의 경우는 createProduct() 메소드 테스트를 1.처음 생성일의자리 productNumber로 생성십의자리 productNumber로 생성백의자리 productNumber로 생성1000개를 넘어가면 예외발생으로 구분하여 테스트 하였습니다.그런데 이 테스트를 한꺼번에 돌렸을 땐 직전 테스트로 이미 저장된 Product에 의해 다음 테스트에 영향을 미쳐 일부 테스트가 실패하는 상황이 발생하였습니다.이상황을 어떻게 해결할 수 있을지 질문 드리고 싶고(sleep() 으로 간격을 주어야 할까요,,)또한 이 원인이 테스트를 한꺼번에 실행시킬 경우,각 테스트 메소드가 각 쓰레드로 동시에 실행되기 때문인지여쭤보고 싶습니다! 감사합니다.
-
미해결Practical Testing: 실용적인 테스트 가이드
주문한 상품 개수만큼 Stock을 감소시키는 로직
안녕하십니까! 저의 경우는 해당 로직을 stockRepository.findByProductNumberIn()이 아니라,일일이 재고와 관련된 ProductNumber에 대하여 stockRepository.findByProductNumber()로조회하여 decreaseQuantity()를 수행하였습니다. 그렇게 하여도, 동일 Stock의 경우 EntityManager에서 조회해오기 때문에 중복된 쿼리가 나가지 않아 어느정도의 성능 감소를 막을 수 있다고 판단하였고, (물론 In절로 한꺼번에 가져오는것 보단 성능이 덜 나올 것 같습니다)그대신에 , 로직이 직관적이라는 장점이 있을 것 같아서 위와 같이 해당 로직을 작성하였습니다. 이에 대해서는 어떻게 생각하시는지 의견 남겨주시면 감사하겠습니다!
-
미해결Practical Testing: 실용적인 테스트 가이드
요청값으로 넘어온 productNumber의 Product가 재고와 관련있는 상품인지 확인하는 로직 질문
안녕하세요! 강의에서는 해당 로직을 ProductType이 BOTTLE이나 BAKERY인 경우에 한하여 true가 되도록 containsStockType() 메소드를 작성하여 판별 해주셨습니다!혹시 이 경우를 stockRepository.existsByProductNumber() 를 호출하여,재고가 있는 상품들만 필터링 해내는 로직으로 작성하게 되면,주문 상품수가 많을 경우 쿼리가 여러번 나가기 때문에 비효율적이어서,요구사항에 따른 검증 로직을 작성하셨는지 여쭙고 싶습니다!
-
미해결Practical Testing: 실용적인 테스트 가이드
@MockBean, @Mock
@MockBean, @Mock 두 개 사용이 계속 헷갈려서 질문 드립니다. 스프링 서버를 띄워서 테스트 할 때 @MockBean을 사용하는 걸로 알려주셨는데 @MockBean도 결국 Mock 객체를 사용하는 거니 @MockBean 대신 @Mock을 써서 테스트를 해도 될 것 같은데 왜 @SpringBootTest나 @WebMvcTest 어노테이션과 @MockBean을 같이 사용해서 테스트 하는 지 궁금합니다.Controller 테스트를 할 때 @WebMvcTest를 사용하기 위해서 @MockBean을 사용하는 걸까요? @WebMvcTest와 @MockBean이 짝궁(?)이어서 이렇게 사용하는걸까요?
-
미해결Practical Testing: 실용적인 테스트 가이드
WebMvcTest에서의 when
Controller 테스트를 하실 때어떤 경우에서는 when으로 값을 세팅해주고어떤 경우에는 사용을 안하시는데기준이 있으실까요
-
미해결Practical Testing: 실용적인 테스트 가이드
강의 코드 질문 드립니다.
안녕하세요. 강의 코드는 혹시 제공 되나요?