학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용]@Test void bulkAgePlus(){ m emberRepository.save( new Member("AAA", 10, null)); m emberRepository.save( new Member("BBB", 15, null)); m emberRepository.save( new Member("CCC", 20, null)); m emberRepository.save( new Member("DDD", 25, null)); m emberRepository.save( new Member("EEE", 30, null)); int count = memberRepository.bulkAgePlus(18); em.flush(); em.clear(); List<Member> result = memberRepository.findByUsername("EEE"); Member findMember = result.get(0); assertThat(count).isEqualTo(3); assertThat(findMember.getAge()).isEqualTo(31); } 여기서 벌크성 연산을 할경우 엔티티 매니저를 거치지 않고 바로 업데이트를 하기에 findById 호출 전에 flush, clear하지 않으면 업데이트 이전에 save된 값이 나오는 것으로 알고 있어(캐쉬된 값) flush, clear를 해주는 것으로 알고 있는데 이때 em.flush()를 해버리면 벌크 연산 값이 아닌 그 이전 값이(save에서 저장한 값 EEE라 가정하면 31이 아닌 30) db에 업데이트 되는 꼴이라 벌크성 연산이 db에 유효하게 저장되려면 em.clear()만 실행 해야되는거 아닌가요?
자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]
31강에서 수업 코드를 잘 따라 쳐서 수업 내용과 똑같은 결과를 확인 할 수 있게 되었는데요. 한 가지 의문점이 들어 질문을 남깁니다. 수업의 마지막 내용인 클린 코드 책이 이미 대출이 되있어 B사용자가 대출을 하려 했으나 대출을 클릭하는 순간 서버 내부 오류입니다. 라는 내용의 경고창이 뜨는걸 확인했는데 영상의 내용에는 진작 대출되어 있는 책입니다 라는 IllegalArgumentException으로 예외처리를 했어서 서버 내부 오류입니다 라는 내용이 아니라 진작 대출되어 있는 책입니다 떠야 하는게 아닌가요? 다음 강의에서 확인할 수 있으려나요~?
각 어노테이션을 언제 주로 사용하는지에 대해 아래와 같이 정리를 했는데 맞게 정리 한 건지 궁금합니다. @Autowired를 사용하는 경우 @ActiveProfiles("test") @SpringBootTest class OrderServiceTest { @Autowired private ProductRepository productRepository; @Autowired private OrderRepository orderRepository; @Autowired private StockRepository stockRepository; @Autowired private OrderService orderService; ... } 스프링 컨텍스트에 실제 빈 객체를 등록하고 해당 빈을 사용합니다. 이렇게 실제 빈을 사용하는 테스트라 실제 동작 검증에 있어서 가장 정확성이 높은 테스트 입니다. @Mockbean과 @Autowired를 섞어 사용하는 경우 @WebMvcTest(controllers = ProductController.class) class ProductControllerTest { @Autowired private MockMvc mockMvc; @Autowired private ObjectMapper objectMapper; @MockBean private ProductService productService; ... } 스프링 컨텍스트에 실제 빈이 아닌 Mock 빈을 등록합니다. 컨트롤러 레이어에 대해서만 단위 테스트를 하고 싶은데 컨트롤러가 서비스 레이어에 의존하고 있으니 이러한 의존을 끊기 위해 @MockBean을 사용하는 방식입니다. @Mock과 @InjectMocks @ExtendWith(MockitoExtension.class) class MailServiceTest { @Mock private MailSendClient mailSendClient; @Mock private MailSendHistoryRepository mailSendHistoryRepository; @InjectMocks private MailService mailService; ... } @Mock을 통해 스프링 컨테이너에 등록되지 않는 가짜 객체를 생성합니다. 그리고 @InjectMocks에 사용된 객체에 @Mock을 통해 생성한 가짜 객체를 주입하는 방식입니다. 스프링 컨테이너가 필요없는 외부 시스템에 대해 테스트를 할때 진행하는 방식입니다. 위 질문 중에 "@Mockbean과 @Autowired를 섞어 사용하는 경우" 코드에 대해 질문이 있습니다. 컨트롤러에 대한 단위 테스트를 하기 위해 @MockBean을 사용하여 서비스에 대한 의존성을 끊는 부분은 이해를 했습니다. 근데 결국 서비스 객체를 가져다 쓰니 서비스가 의존하고 있는 Repository에 대한 부분도 @MockBean을 사용하여 스프링 컨테이너에 Mock을 등록해야 하지 않나 라는 생각이 듭니다. 아래 코드에 대해 질문이 있습니다. 실제 스프링 부트를 실행 하면 각 서비스 객체와 Repository 객체 모두 스프링 컨테이너에 등록되어 서비스 레이어쪽에서 Repository레이어에 의존하는 상황입니다. 저는 스프링 컨테이너에 빈들도 잘 등록되고 서로 잘 데이터를 주고 받는지도 테스트를 해야한다고 생각하는데 아래와 같이 @InjectMocks과 @Mock을 사용하면 스프링 컨테이너와 상관이 없어져서 아래와 같은 상황에서 @InjectMocks과 @Mock을 사용하여 테스트 코드를 작성해도 되는지 궁금합니다. @ExtendWith(MockitoExtension.class) class CustomServiceImplTest { @InjectMocks private CustomServiceImpl customServiceImpl; @Mock private BankRepository bankRepository; @Mock private ProductRepository productRepository; @Mock private OrderRepository orderRepository; ... } 1번 질문과 같이 정리를 했지만 @Autowired와 @Mockbean 사용에 대해 헷갈리는점이 있어 아래 내용을 정리 했는데 맞게 이해를 한건지 궁금합니다. @Autowired를 테스트 코드에서 사용하는 핵심은 해당 기능을 스프링 컨테이너에 등록하는걸 넘어서 해당 객체의 기능을 실제 사용하겠다 라는 의미다. @Mockbean을 테스트 코드에서 사용하는 핵심 이유는 의존 관계를 끊기 위함이다. 예를 들어 컨트롤러 쪽에서 서비스쪽에 강한 의존관계를 가지고 있어 우선 @Mockbean을 통해 생성한 가짜 객체를 스프링 컨테이너에 등록하고 이 가짜 객체를 컨트롤러쪽에서 의존하고 있는 객체에 넣어줘서 의존관계를 끊는다. 주의할점은 @Mockbean을 통해 생성한 가짜 객체의 기능은 사용하지 않는다. 아래 코드에서 @MockBean을 통해 생성한 ProductService 객체는 가짜 객체이므로 ProductRepository 객체를 못 불러오나요? @WebMvcTest(controllers = ProductController.class) class ProductControllerTest { @Autowired private MockMvc mockMvc; @Autowired private ObjectMapper objectMapper; @MockBean private ProductService productService; ... }
[질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 다른 것들은 ...이 추가가 되지 않는데 OrderItem만 ...이 추가 되는 이유가 뭔가요? add를 넣었다고 해서 그런건가요?
7) Ajax 로그인 구현 & CSRF 설정에서 그 다음으로 코드를 수정하는 챕터는 지금 이 파트인거 같은데 갑자기 SecurityConfig 클래스에 customConfigurer, ajaxAuthenticationProvider, ajaxAuthenticationSuccessHandler, ajaxAuthenticationFailureHandler 메서드가 왜 있는건가요.. 하.. 이게 한 두개 챕터면 그냥 실수라고 생각하지만 지금 10챕터 이상이 이렇게 수정하면서 진행하는데 강의 이해도도 떨어지고 시간도 다 잡아먹고 뭐하는건지 모르겠습니다.. 아무리 리팩토링하셨다고 말씀하셨더라도 그럼 리팩토링한 영상을 새로 올리시거나 아니시면 리팩토링 전으로 강의가 흘러가야되는거 아닌가요...답답해서 참다가 글 남깁니다..
===== [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예) [질문 내용] <ResetClose Client> package network.exception.close.reset; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import static util.MyLogger.log; public class ResetCloseClient { public static void main(String[] args) throws IOException, InterruptedException { Socket socket = new Socket("localhost", 12345); log("소캣 연결: " + socket); InputStream input = socket.getInputStream(); OutputStream output = socket.getOutputStream(); // Client <- Server : FIN Thread.sleep(1000); // 서버가 Close() 호출할 때 까지 잠시 대기 // Client -> Server: PUSH[1] output.write(1); // Client <-- Server : RST Thread.sleep(1000); //RST 메시지 전송 대기 try { int read = input.read(); System.out.println("read = " + read); } catch (IOException e) { e.printStackTrace(); } try { output.write(1); } catch (IOException e) { e.printStackTrace(); } } } <ResetCloseServer> package network.exception.close.reset; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import static util.MyLogger.log; public class ResetCloseServer { public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(12345); Socket socket = serverSocket.accept(); log("소캣 연결 : " + socket); socket.close(); serverSocket.close(); log("소캣 종료 : " + socket); } } <클라이언트 결과> C:\Users\nevr\.jdks\openjdk-21.0.2\bin\java.exe "-javaagent:E:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2023.3.3\lib\idea_rt.jar=49785:E:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2023.3.3\bin" -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 -classpath E:\mork\study\java-adv2\out\production\java-adv2 network.exception.close.reset.ResetCloseClient 06:06:39.444 [ main] 소캣 연결: Socket[addr=localhost/127.0.0.1,port=12345,localport=49791] java.net.SocketException: 현재 연결은 사용자의 호스트 시스템의 소프트웨어의 의해 중단되었습니다 at java.base/sun.nio.ch.SocketDispatcher.read0(Native Method) at java.base/sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:46) at java.base/sun.nio.ch.NioSocketImpl.tryRead(NioSocketImpl.java:256) at java.base/sun.nio.ch.NioSocketImpl.implRead(NioSocketImpl.java:307) at java.base/sun.nio.ch.NioSocketImpl.read(NioSocketImpl.java:346) at java.base/sun.nio.ch.NioSocketImpl$1.read(NioSocketImpl.java:796) at java.base/java.net.Socket$SocketInputStream.read(Socket.java:1099) at java.base/java.net.Socket$SocketInputStream.read(Socket.java:1093) at network.exception.close.reset.ResetCloseClient.main(ResetCloseClient.java:29) java.net.SocketException: 현재 연결은 사용자의 호스트 시스템의 소프트웨어의 의해 중단되었습니다 at java.base/sun.nio.ch.SocketDispatcher.write0(Native Method) at java.base/sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:54) at java.base/sun.nio.ch.NioSocketImpl.tryWrite(NioSocketImpl.java:394) at java.base/sun.nio.ch.NioSocketImpl.implWrite(NioSocketImpl.java:410) at java.base/sun.nio.ch.NioSocketImpl.write(NioSocketImpl.java:440) at java.base/sun.nio.ch.NioSocketImpl$2.write(NioSocketImpl.java:819) at java.base/java.net.Socket$SocketOutputStream.write(Socket.java:1195) at java.base/java.net.Socket$SocketOutputStream.write(Socket.java:1190) at network.exception.close.reset.ResetCloseClient.main(ResetCloseClient.java:36) Process finished with exit code 0 네트워크 예외4 - 강제종료 중 받은 메시지인데 수업에 말씀하신 Connection reset , pipe broken 이 아닌 "현재 연결은 사용자의 호스트 시스템의 소프트웨어의 의해 중단되었습니다" 에러 메시지가 나옵니다 위 에러메시지에 대해 궁금합니다! (사용자의 호스트 시스템?? 이게 어떤 시스템인지.., 방화벽 문제인지, 보안소프트웨어를 말하는지) 강의 너무 잘듣고 있습니다!! 영환쌤 늘 감사드립니다.
@Service @RequiredArgsConstructor public class MemberService { private final MemberRepository memberRepository; @Transactional //변경 public Long join(Member member) { validateDuplicateMember(member); //중복 회원 검증 memberRepository.save(member); return member.getId(); } } @Repository @RequiredArgsConstructor public class MemberRepository { private final EntityManager em; public void save(Member member) { em.persist(member); } public Member findOne(Long id) { return em.find(Member.class, id); } } --------------------------------------------------------------------------- // 테스트 코드 @Transactional public class MemberServiceTest { @Autowired MemberService memberService; @Autowired MemberRepository memberRepository; @Test public void 회원가입() throws Exception { //Given Member member = new Member(); member.setName("kim"); //When Long saveId = memberService.join(member); //Then assertEquals(member, memberRepository.findOne(saveId)); } } 회원 도메인 개발 파트의 마지막 강의에 있는 테스트 부분입니다 테스트는 성공이고, 테스트 결과 로그에는 member 객체에 대한 select sql이 찍힙니다 그런데 테스트 로그에 왜 select sql이 나오는지 잘 모르겠습니다 제가 이해하고 있는 내용은 이렇습니다 //When Long saveId = memberService.join(member); 위 코드에서 insert sql 이 생성되지만 내부 트랜잭션이라 커밋하지 않아서 해당 엔티티가 영속성 컨텍스트에만 추가된 상태 //Then assertEquals(member, memberRepository.findOne(saveId)); 위 코드에선 영속성 컨텍스트의 member를 가져오니 select sql 이 실행되지 않습니다 //When Long saveId = memberService.join(member); //Then assertEquals(member, memberRepository.findOne(saveId)); 그리고 테스트 코드에서 @Transactional 은 롤백이니 join()의 결과가 롤백됩니다 join() 은 롤백됬으니 테스트 결과 로그에 insert sql 이 나오지 말아야 하고, 영속성 컨텍스트의 member를 조회했으니 select sql 도 나오지 말아야 하는 것으로 예상됩니다 하지만 insert sql 은 예상한대로 테스트 결과에 나오지 않는데, select sql 은 나오는 이유를 모르겠습니다 해결했습니다 validateDuplicateMember(member) 중복 회원 검증하는 메서드에서 select sql을 호출하고 있었습니다 em.persist() 보다 먼저 호출하기 때문에 DB에서 바로 조회해오고 있었습니다 이걸 못보다니..
List<Integer> list1 = new ArrayList<>(); List<Integer> list2 = new ArrayList<Integer>(); 객체의 타입에는 들어갈 데이터의 타입을 명시해 주어야 하지만 인스턴스를 생성할 때는 타입추론으로 인해 다이아몬드에 타입을 입력하지 않아도 되는 부분에서 궁금증이 생겼습니다. 타입추론은 인스턴스 생성 시 개발자의 편의를 위해 몇 자 줄여주는 정도인가요? 아니면 다른 부가적인 장점이 있는지 궁금합니다. 컴파일러가 타입을 추론하기 위한 시간이 추가적으로 소요될 것 같은데(고려할 정도는 아니겠지만...) 오히려 타입추론으로 최적화 적인 방면으로 이점도 있을까요?..
ArrayList는 배열을 기반으로 만든 List이며 LinkedList는 객체의 참조로 연결된 List로 이해했습니다. 요즘에는 메모리 용량이 많이 크기 때문에 고려하지 않아도 된다고 생각하는데 궁금증이 있어 질문을 남깁니다. LinkedList는 데이터가 추가 될 때 마다 새로운 Node를 만들어서 현재 가지고 있는 데이터의 크기만큼 메모리를 차지하는 반면 ArrayList는 들어있는 데이터 크기가 일정 크기를 넘는 경우 더 많은 데이터를 저장할 수 있는 새로운 Array를 생성하여 반환하기 때문에 동일한 개수의 데이터를 저장해도 ArrayList가 메모리 상에서 차지하는 크기가 크다고 생각하면 되나요?
- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요! - 먼저 유사한 질문이 있었는지 검색해보세요. - 서로 예의를 지키며 존중하는 문화를 만들어가요. - 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요. 안녕하세요, 2강 코틀린에서 null을 다루는 방법 수강중 궁금한 지점이 생겨 문의드립니다. name이라는 필드에 NotNull 어노테이션을 달아주어서 인스턴스 초기화시 null값은 받을 수 없게 하고싶었는데이런 경우에는 null을 대입해도 에디터상에서 에러를 짚어주지 못하더라구요.회사 프로젝트를 전환하는 과정중에는 이런 문제가 꽤나 발생할 것 같은데 좋은 해결책이 있을까요? package com.lannstark.lec02; import org.jetbrains.annotations.NotNull; public class Person { @NotNull private final String name; public Person(String name) { this.name = name; } public String getName() { return name; } } package com.lannstark.lec02 fun main() { val person = Person(null) startsWithA(person.name) }
[질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (아니오) [질문 내용] 여기에 질문 내용을 남겨주세요. 컬렉션 프레임워크9에서 문제와풀이2의 문제6번에 대해 여쭤봅니다. memberMap이라는 해시맵에서 첫번째 매개변수로 member.getId 가 들어가고 두번째 매개변수로 member클래스가 들어가는데 첫번째 매개변수가 member클래스의 멤버변수이어야 하는 이유가 있을까요? 문제를 풀던 중에 아직은 잘 모르겠지만 member클래스의 멤버변수 두개를 memberMap이라는 해시맵에 두개를 지정해도 될거같기도 한데(제 극히 초보인 관점에서 본 추측일 뿐입니다.그렇게 풀어볼 능력까진 없어서요.) 굳이 두번째에 클래스를 넣으시고 첫번째에 클래스의 멤버변수 하나를 넣으신 이유가 궁금합니다. 제 짧은 시각으로 보면 중복 같아 보여서요 질문6번의 의도가 파악이 안 돼서 궁금하여 여쭤봅니다.
강의를 보고 기존 프로젝트에 작성하지 않았던 테스트 코드를 작성하면서 공부하고 있습니다. 도메인 모듈같은 경우 어떠한 의존성도 가지고 있지 않은 POJO 형태로 코드를 작성해서 단위 테스트로 검증할 수 있었습니다. Crawling 모듈의 경우 Jsoup이라는 라이브러리를 사용하여 특정 URL의 HTML을 불러오고, 해당 HTML에서 필요한 정보를 추출하는 코드를 가지고 있습니다. 이때, 전체적으로 Mock을 사용하여 테스트를 진행하고자 하였는데 라이브러리의 특성 때문에 stubbing을 작성하는데 불편함을 느꼈습니다. 그래서 HTML을 임의로 만들고, HTML을 불러오는 메서드만 stubbing을 적용하려고 하는게 더 효율적이지 않을까 라는 생각이 들었습니다. 외부 라이브러리를 사용하는 코드에서 테스트 작성이 미숙한 것 같아서 어떤 방향이 더 좋을지 질문드리고 싶습니다. 아래 두 코드는 동일한 테스트를 진행하고 있는 코드가 아닌점 참고바랍니다. @Mock private lateinit var webPageLoader: WebPageLoader<Document> @InjectMocks private lateinit var dietParser: DietParser fun parse() { // given val mockDocument = mock(Document::class.java) val mockRows = Elements() val row1 = mock(Element::class.java) val row2 = mock(Element::class.java) val row3 = mock(Element::class.java) mockRows.add(row1) mockRows.add(row2) mockRows.add(row3) val columns1 = Elements( mock(Element::class.java).apply { given(text()).willReturn("2024.10.23") }, mock(Element::class.java), mock(Element::class.java), mock(Element::class.java).apply { given(text()).willReturn("Menu 1, Menu 2") } ) val columns2 = Elements( mock(Element::class.java).apply { given(text()).willReturn("교직원식당") } ) val columns3 = Elements( mock(Element::class.java).apply { given(text()).willReturn("2024.10.24") }, mock(Element::class.java), mock(Element::class.java), mock(Element::class.java).apply { given(text()).willReturn("Menu 3, Menu 4") } ) given(webPageLoader.getHTML(anyString())).willReturn(mockDocument) given(mockDocument.select(anyString())).willReturn(mockRows) given(row1.select(anyString())).willReturn(columns1) given(row2.select(anyString())).willReturn(columns2) given(row3.select(anyString())).willReturn(columns3) // when val result = dietParser.parse() // then assertThat(result).hasSize(2) .extracting("date", "menus") .containsExactly( tuple(LocalDate.of(2024, 10, 23), listOf("Menu 1", "Menu 2")), tuple(LocalDate.of(2024, 10, 24), listOf("Menu 3", "Menu 4")), ) } @Mock private lateinit var webPageLoader: WebPageLoader<Document> @InjectMocks private lateinit var parser: DepartmentNoticeParser fun parse() { // given val html = """ <table class="board-table"> <tbody> <tr> <td class="td-num">2</td> <td class="td-subject"><a href="javascript:fnView('2','url','title','2')">공지 제목 2</a></td> <td class="td-write">작성자 2</td> <td class="td-date">2024.10.02</td> </tr> <tr> <td class="td-num">1</td> <td class="td-subject"><a href="javascript:fnView('1','url','title','1')">공지 제목 1</a></td> <td class="td-write">작성자 1</td> <td class="td-date">2024.10.01</td> </tr> </tbody> </table> """.trimIndent() val document: Document = Jsoup.parse(html) given(webPageLoader.getHTML(anyString())).willReturn(document) parser.initialize(Major.COMPUTER_SOFTWARE_ENGINEERING) // when val notices = parser.parse() // then assertThat(notices).hasSize(2) .extracting("number", "title", "author", "date", "url") .containsExactlyInAnyOrder( tuple( 2, "공지 제목 2", "작성자 2", LocalDate.of(2024, 10, 2), "https://www.dongyang.ac.kr/combBbs/2/url/2/view.do?layout=unknown" ), tuple( 1, "공지 제목 1", "작성자 1", LocalDate.of(2024, 10, 1), "https://www.dongyang.ac.kr/combBbs/1/url/1/view.do?layout=unknown" ), ) }
1. 강의 내용과 관련된 질문인가요? 예 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요?예 3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예 [질문 내용] 객체와 같이 참조형 타입의 변수를 메서드의 매개인자로 넘기게 되면 값이 "복사"되어 넘어가는 것 이라고 이해했습니다. 그럴경우, 다음의 코드를 실행 했을 때 출력되는 결과는 "abcd" 입니다. 참조 값도 마찬가지로 "복사"를 통해 넘기기 때문에 가능한 부분일까요? public static void main (String[] args) { String str = "abcd" ; changeStr (str); System. out .println(str); } public static void changeStr (String str) { str = new String( "new String!" ); }
학습 관련 질문을 남겨주세요. 어떤 부분이 고민인지, 무엇이 문제인지 상세히 작성하면 더 좋아요! 먼저 유사한 질문이 있었는지 검색해 보세요. 서로 예의를 지키며 존중하는 문화를 만들어가요. 강의에서 테스트 given절에서 팩토리 메서드를 통한 객체 생성은 어떠한 의도가 들어갈 수 있으므로 지양하라고 하셨습니다. 관련하여 질문이 있습니다. 예를 들어 다음과 같은 팩토리 메서드가 있다고 하면, public class Coffee { private String type; private int size; public Coffee(String type, int size) { this.type = type; this.size = size; } } public class SeasonalCoffeeFactory { public static Coffee createCoffee(String season) { switch (season.toLowerCase()) { case "summer": return new Coffee("Iced Coffee", 50); case "winter": return new Coffee("Hot Coffee", 30); case "spring": return new Coffee("Latte", 40); case "fall": return new Coffee("Pumpkin Spice Latte", 45); default: throw new IllegalArgumentException("Unknown season: " + season); } } } 여름 시즌 커피에 대한 테스트 코드는 다음과 같을 겁니다. @Test public void testCreateSummerCoffee() { Coffee coffee = SeasonalCoffeeFactory.createCoffee("summer"); assertEquals("Iced Coffee", coffee.getType()); assertEquals(50, coffee.getSize()); } 이때 테스트 코드는 시즌에 맞는 커피 메뉴를 given절에 생성한 후 타입 일치여부만 판단하면 됩니다. 하지만 이 부분을 팩토리 메서드로 작성하지 않게되면 커피를 생성함에 있어 if ("summer".equalsIgnoreCase(season)) { coffee = new Coffee("Iced Coffee", 50); } else if... 와 같은 부분이 테스트 코드의 given절에 들어가야하지 않나 싶습니다. 물론 이런 부분에 대해서 if라는 논리구조가 들어갔으니 한번 더 테스트 코드 메서드가 분리되어야하는건가 싶기도 한데 확신이 잘 안 서서 질문 드리고 싶습니다. 긴 글 읽어주셔서 감사합니다.
TestBeanPostProcessor 가 BeanPostProcessor인터페이스를 implements했고 BeanPostProcessor에 정의되어있는 메서드들을 오버라이딩 안하면 자동으로 오류가 뜨면서 오버라이딩 해라고 경고가 떠야 정상 아닌가요? 강사님 강의에서도 제 컴퓨터에서도 따로 오류가 뜨지 않아서 궁금해서 질문 남깁니다.
default-init-method와 , default-destroy-method를 bean태그 안이 아니고 beans 태그 안에 넣으셨는데, 이렇게 하면 default-destroy-method나 default-init-method를 bean 태그 안에 안 넣으면 자동으로 실행을 해주는 거잖아요. 그럼 만약에 TestBean2 클래스안에 default_init, default_destroy와 똑같은 이름의 메서드가 없으면 실행 안하는걸로 이해했는데 맞나요? 그리고 id가 t1인 bean태그에 init-method, destroy-method를 안썼다면 beans태그에 작성해놓은 default 속성들이 실행이 될텐데 똑같은 이름의 메서드가 있으면 id-t1인 bean 객체에도 default 속성에 지정해놓은 메서드가 실행되는건가요?