묻고 답해요
160만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨Spring Boot TDD - 입문부터 실전까지 정확하게
프로젝트 규모가 큰 경우 @SpringBootTest 실행 속도 문제
안녕하세요, 강사님.저는 백엔드 1년 차 주니어 개발자입니다. 강사님 덕분에 TDD 학습을 차근차근 진행하고 있는데, 한 가지 궁금증이 생겨 질문드립니다. 현재 강의에서는 매번 API 기능을 구현할 때마다 @SpringBootTest 를 사용하여 테스트하고 계신데요. 만약 프로젝트 규모가 엄청 커져서 컨텍스트 로딩 시간이 5초 이상이 소요되는 경우,테스트 결과를 기다리느라 “개발 흐름이 끊기는” 문제가 발생할 것 같은데요. 현업에서는 이 부분을 어떻게 관리하시는지 궁금합니다. 매번 @SpringBootTest를 그대로 사용하며 시간을 감수하시는지특정 테스트만 빠르게 실행하는 슬라이스 테스트(@WebMvcTest 등)를 병행하시는지그 외 다른 최적화 기법이 있는지 조언 부탁드립니다. 😊
-
미해결더 자바, 애플리케이션을 테스트하는 다양한 방법
테스트 반복하기 관련 질문입니다
@DisplayName("파라미터 테스트") @ParameterizedTest(name = "{index} {displayName} message={0}") @ValueSource(ints = {10, 20, 40}) void parameterizedTest(Study study){ System.out.println(study.getLimit()); }Junit5 테스트 반복하기 2부에서 이 부분 질문드리려 합니다. 강의에서는 Study 타입으로 받아서 객체를 생성하고 getLimit으로 값 가져오는 것까지 묵시적으로 진행이 잘 되었습니다만, 제 환경에서는 ```javaError converting parameter at index 0: No built-in converter for source type java.lang.Integer and target type com.example.testpractice.Studyorg.junit.jupiter.api.extension.ParameterResolutionException: Error converting parameter at index 0: No built-in converter for source type java.lang.Integer and target type com.example.testpractice.Study at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183) at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197) at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179) at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197) at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183) at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197) at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183) at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)``` 와 같은 에러가 발생해서 Junit이나 JDK의 버전에 따라 스펙이 바뀌었는지 궁금해져서 질문드립니다
-
미해결스프링부트 JUnit 테스트 - 시큐리티를 활용한 Bank 애플리케이션
요청/응답 DTO 관련 문의
안녕하세요, dto 관련 문의드립니다. 요청/응답 DTO를 왜 static으로 만드나요?이전 데이터가 유지되지 않나요?? 매번 객체를 만들면 안되나요? @Getter @Setter public static class AccountWithdrawReqDto { @NotNull @Digits(integer = 4, fraction = 4) private Long number; @NotNull @Digits(integer = 4, fraction = 4) private Long password; @NotNull private Long amount; @NotEmpty @Pattern(regexp = "^(WITHDRAW)$") private String transactionType; }//ATM -> 계좌 @Transactional public AccountWithdrawRespDto 계좌출금(AccountWithdrawReqDto accountWithdrawReqDto, Long userId) { //1. 0원 체크 if (accountWithdrawReqDto.getAmount() <= 0L) throw new CustomApiException("0원 이하의 금액을 출금할 수 없습니다."); //2. 출금 계좌 확인 Account withdrawAccountPS = accountRepository.findByNumber(accountWithdrawReqDto.getNumber()) .orElseThrow(() -> new CustomApiException("계좌를 찾을 수 없습니다.")); //3. 본인 확인 withdrawAccountPS.checkOwner(userId); //4. 패스워드 확인 withdrawAccountPS.checkPassword(accountWithdrawReqDto.getPassword()); //5. 출금계좌 잔액 확인 // withdrawAccountPS.checkBalance(accountWithdrawReqDto.getAmount()); //6. 출금 (잔액 확인이 누락되면 안되므로 출금 메소드에 녹인다!) withdrawAccountPS.withdraw(accountWithdrawReqDto.getAmount()); //7. 거래 내역 Transaction transaction = Transaction.builder() .withdrawAccount(withdrawAccountPS) .depositAccount(null) .withdrawAccountBalance(withdrawAccountPS.getBalance()) .depositAccountBalance(null) .amount(accountWithdrawReqDto.getAmount()) .sender(withdrawAccountPS.getNumber().toString()) .receiver("ATM") .transactionType(TransactionEnum.WITHDRAW) .build(); Transaction transactionPS = transactionRepository.save(transaction); return new AccountWithdrawRespDto(withdrawAccountPS, transactionPS); }
-
미해결쥬쥬와 함께 하루만에 끝내는 스프링 테스트
S3통합 테스트 질문
통합 테스트 돌리는 중에java.lang.RuntimeException: java.net.URISyntaxException: Expected scheme-specific part at index 10: localhost:이런 에러가 나서 헤매고 있습니다 ㅜㅜ노션이랑 강의 다시 돌려보면서 틀린 부분 찾고 있는데 없는 것 같고요 scheme문제라고 해서 properties파일을aws.endpoint=localhost:4566 이거 에서aws.endpoint=http://localhost:4566 요걸로 바꿔도 에러가 발생하네요 어떻게 해결해야하나요?
-
미해결쥬쥬와 함께 하루만에 끝내는 스프링 테스트
성적 저장 어플 만들기 강의 관련 질문
강의 17분쯤에 save메서드를 postman에서 테스트를 해보았는데 Internal Server Error가 떠서 확인해보니cannot deserialize from Object value (no delegate- or property-based Creator) 에러가 뜨는 것을 확인할 수 있었습니다. 그래서 기존에@Getter @AllArgsConstructor public class SaveExamScoreRequest { private final String studentName; private final Integer korScore; private final Integer englishScore; private final Integer mathScore; }이렇게 써져있는 코드를@Getter @AllArgsConstructor @NoArgsConstructor public class SaveExamScoreRequest { private String studentName; private Integer korScore; private Integer englishScore; private Integer mathScore; }이렇게 바꾸니 정상적으로 응답을 반환함을 확인할 수 있었습니다.알아보니 해당 에러는 jackson생성자가 빈 생성자가 없는 객체를 만드는 법을 모르기 때문에 뱉는 에러라고 설명되어있어서 @NoArgsConstructor어노테이션을 추가하였고 final을 지워주었습니다.근데 강사님의 코드는 잘 돌아가는데 왜 제 코드는 저런 에러가 발생하는지 모르겠습니다. 혹시 스프링 버전하고도 관련이 있나요? (저는 현재 spring boot 3.4.1 버전을 사용하고 있기는 합니다.)
-
미해결더 자바, 애플리케이션을 테스트하는 다양한 방법
Testcontainers ddl-auto 동작 시점
spring boot, jpa, junit5, testcontainers를 이용해서 테스트 코드를 작성하고 있습니다.총 12개의 테스트 클래스를 만들었고 각 클래스마다 testcontainers 객체를 static으로 가지고 있고 모두 @SpringBootTest, @Testcontainers 어노테이션만 추가했습니다.(Controller 테스트 시 @AutoConfigureMockMvc 어노테이션 추가)jpa의 ddl-auto 값을 create-drop으로 설정했기 때문에 gradle test를 실행할 때 예상되는 결과는 각 클래스를 테스트할 때마다 테이블이 새로 생성되어야 할 것 같은데 실제로는 총 2번 생성됩니다.각 클래스마다 Testcontainers를 적용했음에도 불구하고 실패한 로그를 보면 이전 클래스에서 사용한 데이터를 다음 클래스에서도 사용하는 것처럼 보이는데 테스트 실행 시 각 테스트 클래스마다 jpa의 ddl-auto 속성이 동작하지 않는 이유각 클래스에 Testcontainers를 적용했음에도 불구하고 생성된 데이터베이스가 컨테이너들이 공유하는 이유가 궁금합니다.
-
미해결더 자바, 애플리케이션을 테스트하는 다양한 방법
testcontainers DB 공유 이슈
junit5, jpa를 이용해서 테스트 코드를 작성하고 testcontainers를 이용해서 테스트를 수행하려고 합니다.A entity는 n개의 B entity를 가지고 있고, B entity는 C entity를 가지고 있습니다.A에 관련된 테스트 클래스, B에 관련된 테스트 클래스(A entity 이용), C에 관련된 테스트 클래스(A, B entity 모두 이용)를 클래스별로 각각 테스트를 진행하면 모두 정상적으로 통과합니다. 하지만 gradle test로 전체 클래스에 대해서 테스트를 진행하면 종종 실패합니다.로그를 확인했는데 C 클래스를 테스트하면서 db에 A, B, C 데이터가 insert됐고 이어서 B 클래스를 테스트할 때 @BeforeAll로 B, A 순서로 데이터를 삭제하는 과정에서 C 데이터가 남아있기 때문에 B 데이터를 삭제할 수 없어 테스트가 실패합니다. 이해하기로는 testcontainers가 각 클래스에서 static으로 선언되면 테스트 시작 시점에 컨테이너가 생성되어 순수한 상태의 db로 테스트를 진행할 수 있고 테스트가 끝나면 컨테이너가 삭제되어 db도 자연스럽게 초기화된다고 생각했는데실제로는 하나의 db를 여러 개의 container가 공유해서 사용하는 것처럼 보입니다. 컨테이너 생성이 db의 생명주기에 영향을 주나요?
-
미해결쥬쥬와 함께 하루만에 끝내는 스프링 테스트
강의를 수강하면서 2가지 질문이 생겼습니다
안녕하세요 쥬쥬님의 강의를 보면서 테스트 코드 작성에 도움을 많이 받고 있습니다. 감사합니다. 질문이 있어서 글을 올려드립니다. 질문1.application.yml 에서 mysql, redis, kafka 의 호스트를 컨테이너 이름으로 지정해주면 굳이 IntegrationTestInitializer 정적 클래스의 initialize() 메서드를 구현해 동적으로 호스트와 아이피를 지정할 필요가 없을 것이라고 생각했습니다. 왜 application.yml 에서 각 모듈의 호스트를 localhost 로 지정해주셨는지 여쭤보고 싶습니다. 질문2.redis, kafka 에 특화된 테스트 컨테이너 모듈을 사용하셨는데, 이러한 모듈을 사용하지 않고 그냥 testImplementation "org.testcontainers:testcontainers:1.19.0" 만을 사용해서 테스트 컨테이너를 구동시켜 테스트해도 되는지 여쭤보고 싶습니다. 예를 들어 이런 식으로 입니다. 질문 읽어주셔서 감사합니다.
-
미해결재고시스템으로 알아보는 동시성이슈 해결방법
Pessimistic Lock 전체 테스트 오류 문의
안녕하세요. Pessimistic Lock 소스에서 각각의 테스트 하나하나는 통과하는데요. 테스트 코드 전체로 돌리면 에러가 나더라고요. public interface StockRepository extends JpaRepository<Stock, Long> { @Lock(LockModeType.PESSIMISTIC_WRITE) @Query("select s from Stock s where s.id = :id") Stock findByIdWithPessimisticLock(@Param("id") Long id); } StockServiceTest.javapackage com.example.stock.service; import com.example.stock.domain.Stock; import com.example.stock.repository.StockRepository; import org.junit.jupiter.api.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest class StockServiceTest { @Autowired private PessimisticLockStockService stockService; @Autowired private StockRepository stockRepository; @BeforeEach public void before() { stockRepository.saveAndFlush(new Stock(1L, 100L)); } @AfterEach public void after() { stockRepository.deleteAll(); } @Test @DisplayName("재고1개 감소 테스트") public void 재고감소() { stockService.decrease(1L, 1L); //100 - 1 = 99 Stock stock = stockRepository.findById(1L).orElseThrow(); assertThat(stock.getQuantity()).isEqualTo(99L); } @Test @DisplayName("동시에 100개 요청 테스트") public void 동시에_100개_요청() throws InterruptedException { int threadCount = 100; ExecutorService executorService = Executors.newFixedThreadPool(32); CountDownLatch countDownLatch = new CountDownLatch(threadCount); for (int i = 0; i < threadCount; i++) { executorService.submit(() -> { try { stockService.decrease(1L, 1L); } finally { countDownLatch.countDown(); } }); } countDownLatch.await(); Stock stock = stockRepository.findById(1L).orElseThrow(); assertThat(stock.getQuantity()).isEqualTo(0L); } } 이런 오류가 나는데 @BeforeEach에서 새로 등록하고 @AfterEach에서 delete를 해줘서 각각의 테스트에 영향이 없을거 같은데 왜 나는지 잘 모르겠어요 ㅠ github : https://github.com/nhs0912/stock
-
미해결스프링부트 JUnit 테스트 - 시큐리티를 활용한 Bank 애플리케이션
안녕하세요 인증이 필요한 url을 위하여 /s를 붙이는것에 대해 질문있습니다.
안녕하세요 인증이 필요한 url을 위하여 /s를 붙이는것에 대해 질문있습니다.실무에서도 url분리를 위해 /s만 붙이기도 하나요?아니라면 url 설계를 어떤식으로 해야할지 팁을 알고싶습니당.
-
미해결스프링부트 JUnit 테스트 - 시큐리티를 활용한 Bank 애플리케이션
validation aop사용에 대해서 질문있습니다.
@ResponseStatus(HttpStatus.BAD_REQUEST)@ExceptionHandler(BindException.class)public ApiResponse<Object> bindException(BindException e) {이런식으로 전역적으로 validation을 해주면 aop를 사용하지 않고 더 편하고 어노테이션도 안달아줘도 될거같은데 aop를 사용하면 장점이 무엇인가요?
-
미해결쥬쥬와 함께 하루만에 끝내는 스프링 테스트
github action
좋은 강의 너무 잘 들었습니다.그런데 github action 파일에서 jdk 설치는 왜 필요한 것일까요?그리고 jdk 설치 등 job의 실행 주체는 github action 이라는 깃허브 repository 내장된 서버라고 보면 될까요?감사합니다.
-
미해결쥬쥬와 함께 하루만에 끝내는 스프링 테스트
Model 의존 java.lang, jakarta
좋은 강의 잘 듣고 있습니다.<의존성 검증: Controller는 Entity를 사용하고 있을까?> 강의에서요.11:40초 쯤에서 에러 로그들이 의미하는 것이 궁금합니다.Class <com.jyujyu.dayonetest.model.StudentFail> is annotated with <jakarta.persistence.Entity> Class <com.jyujyu.dayonetest.model.StudentPass> extends class <java.lang.Object>..위 같은 에러는 해당 모델들(StudentFail, StudentPass) 이 @Entity 로 정의되었으므로 jakarta.persistence.Entity, jakarta.persistence.Table> 에서 사용된 것은 알겠는데java.lang.Object 로 사용된 것은 어떻게 봐야 하나요?단순 Object 라면, 모든 클래스는 Object 를 의존하는 것 아닌가요?미리 답변 감사합니다!
-
미해결Kotlin으로 개발하는 Spring Boot Web MVC
[제발 부탁 드립니다.]react와 스프링 부트간 통신하는데 통신이 안되네요. 무엇이 문제일까요??
=========중용한 부분이 오타가 있어서 수정합니다================ 안녕하세요. 완강을 한후에 제가 프론트엔드와 백엔드간 통신을 확인하려합니다. 그런데 예상과 다르네요...일단 프론트 엔드 (react을 먼저 보여드릴께요) const handleSubmit = (event) => { fetch('http://localhost:8080/api/posttest', { method: 'POST', // *GET, POST, PUT, DELETE 등 body: JSON.stringify({ name: 'foo', email: 'kjy@gmail.com', message: '1', }), headers: { 'Content-type': 'application/json; charset=UTF-8', }, }) .then((response) => response.json()) .then((json) => alert(json)); alert("test") };이렇게 작성하고 ...백엔드( spring boot)는@RestController @RequestMapping("/api") class _____ApiController{ @PostMapping(path=["/posttest"]) fun postTest( @RequestBody body: BodyClass ): ResponseEntity<String> { println(body) return ResponseEntity.ok().body("test") } }data class BodyClass( var name: String = "", var email: String = "", var message: String = "" ) 이렇게 코딩 했는데 ..분명해서 테스트 해서 정상 확인했는데 ...react에서 전송하면 postTest 함수를 진입하지 않습니다. ... 백엔드쪽에 코드를 좀 바꿔서 Requestbody에서 json 파일 그대로 받자는 식으로 아래처럼 바꿨어요fun postTest( @RequestBody json: String ): ResponseEntity<String> { println(body) return ResponseEntity.ok().body("test") } react는 json 형식인지 표시하는걸 지웠는데fetch('http://localhost:8080/api/posttest', { method: 'POST', // *GET, POST, PUT, DELETE 등 body: JSON.stringify({ name: 'foo', email: 'kjy@gmail.com', message: '1', }), headers: { // 삭제 }, }) .then((response) => response.json()) .then((json) => alert(json)); alert("test" 백엔드의 postTest함수에 진입 합니다.프론트 엔드에서 전송한 json 내네요용이 전송됩니다.이게 ... 새롭게 프로젝트를 만들어도 똑같고 프론트 엔드 백엔드 모두 새롭게 프로젝트를 만들어서 테스트 해도 똑같아요...스프링 부트에서 잘못된건지... react에서 잘못된건지 잘 모르겠네요...아마도 스프링 부트에서 뭔가 잘못된거 같은게 api 서버가 있어서 그걸로 접속하니깐 되긴 하네요...그렇다면 스프링 부트에서 잘못한건지..분명 스프링 부트에도 문제가 없어 보이는데힘드네요 ... ㅠ.ㅠ 살려주세요 ㅠ.ㅠ 몇일째 못풀고 있어요...
-
미해결쥬쥬와 함께 하루만에 끝내는 스프링 테스트
put api 500 서버에러응답 문제
선생님 안녕하세요 두번째 강의 막 시작했는데요...^^강의 아주 초반에는 postman으로 성적저장 put api 보낼 때는 스프링 서버가 잘 응답했는데, 오히려성적저장 애플리케이션 개발 후 마지막으로 테스트 put api 보낼때는 응답못하고 500 에러 뱉으면서 local host access denied 이런 에러가 갑자기 나오는데 구글링하고 chatGPT 물어봐도 해결이 안 되요. 아무래도 db쪽 문제인 것 같은데 뭐가 문제일까요? 도와주세요.
-
미해결쥬쥬와 함께 하루만에 끝내는 스프링 테스트
스프링 버전
안녕하세요.수업 잘 듣고 있는 수강생입니다.별개로 회사에서 스프링버전 1버전도 있고 2버전도 있는데요, 그런 경우는 junit5 라이브러리를 따로 임포트 해서 사용하지 못할까요?
-
미해결더 자바, 애플리케이션을 테스트하는 다양한 방법
질문있습니다.
현재 스프링부트는 3.x버전대인데..버전대 맞춰서 예제나 소스코드를 변경해야할까요?..강의버전대는 2.1? 버전으로 알고있습니다..(지원하지 않은 코드가 있을경우)아울러 9월 이후로 답변주시지 않으신것같은데..질문이나 답변은 더 이상 안하시는것일까요?
-
미해결스프링부트 JUnit 테스트 - 시큐리티를 활용한 Bank 애플리케이션
Dummy 클래스 위치에 대한 질문
현재 "회원가입 서비스 코드 리팩토링"까지 봤는데 Dummy는 테스트 단에서만 쓰이는 것으로 보입니다. 그러면 더미 클래스를 main.config.dummy가 아닌 test.dummy에 작성하는 것이 의미가 분명하고 추후 개발 및 배포에서도 용이한 것 아닌지 의문이 들어 질문 드립니다! config에 작성한 이유와 test에 작성하지 않은 이유가 궁금합니다.!
-
미해결스프링부트 JUnit 테스트 - 시큐리티를 활용한 Bank 애플리케이션
테스트 방식에 관해서 질문이 있어요
안녕하세요 강사님 강의 듣고 많이 배우고 있습니다.다름이 아니라 테스트 방식에 질문이 있어서 문의 드립니다.현재 테스트는 서비스 코드를 먼저 짜고 테스트를 진행하는데테스트 방식에는 테스트 코드를 먼저 짜고 서비스 코드를 만들어가는 형식도 있더라구요..둘 차이점이 혹시 있을까요..
-
미해결쥬쥬와 함께 하루만에 끝내는 스프링 테스트
flyway 컨테이너가 동작하지 않습니다.
안녕하세요! 강의 잘 듣고 있는 중에 문의드립니다.현재 컨테이너 기반 테스트 환경을 구성한 상태로, 실제 데이터로 테스트를 진행하기에 앞서 맥북으로 진행하던 내용을 pc에서도 진행하고자 코드를 그대로 pull해온 상태입니다. 근데 컨테이너들이 정상적으로 동작하는 것 같지 않아 문의드립니다...ㅠ스프링 로그에서는 마이그레이션 성공시 출력될 로그를 확인하는 정규식 표현에 매칭되는 로그를 찾지 못해 timeout이 나는 것으로 나오고, 도커 데스크탑을 보고 있으면 다른 컨테이너들은 정상적으로 실행되는데에 반해 flyway 컨테이너(local-db-migrate)만 계속 Exited와 Restart를 반복하고 있습니다. 해당 컨테이너 로그를 살펴보면 계속해서 아래와 같이 출력됩니다 ㅠㅠ /flyway/conf/flyway.conf는 컨테이너의 볼륨에서 해당 파일을 찾지 못했다는 것인가요? 혹시 해결 방안을 아시면 답변 부탁드리겠습니다. 참고로 OS는 윈도우입니다.infra/test/docker-compose.yaml 파일db/flyway.conf 파일