본문 바로가기
프로젝트

계좌 시스템 개발 프로젝트

by Lv.1 ysg 2024. 1. 26.

 

1. inner class 활용 방법

public class CreateAccount {
    public static class Request{
        
    }

    public static class Response{

    }
}

@PostMapping("/account")
public String createAccount(
        @RequestBody @Valid CreateAccount.Request account) {
    accountService.createAccount();
    return "success";
}

 

2. static 메소드의 활용 방법

특정 엔티티에서 특정 dto로 변환할때 생성자를 사용해서 변환 하는것보다 가독성이 좋고 안전하게 생성할수 있다.

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class Response{
    private Long userId;
    private String accountNumber;
    private LocalDateTime registeredAt;

    public static Response from(AccountDto accountDto){
        return Response.builder()
                .userId(accountDto.getUserId())
                .accountNumber(accountDto.getAccountNumber())
                .registeredAt(accountDto.getRegisteredAt())
                .build();
    }
}

 

 

3. MockBean 

https://jojoldu.tistory.com/226

 

SpringBoot @MockBean, @SpyBean 소개

안녕하세요? 이번 시간엔 SpringBoot의 @MockBean, @SpyBean 예제를 진행해보려고 합니다. 모든 코드는 Github에 있기 때문에 함께 보시면 더 이해하기 쉬우실 것 같습니다. (공부한 내용을 정리하는 Github

jojoldu.tistory.com

 

위 링크에서 가져온 내용이다 

 

Mock은 껍데기만 있는 객체를 얘기합니다.
인터페이스의 추상메소드가 메소드 바디는 없고 파라미터 타입과 리턴타입만 선언된 것처럼, Mock Bean은 기존에 사용되던 Bean의 껍데기만 가져오고 내부의 구현 부분은 모두 사용자에게 위임한 형태입니다.
즉, 해당 Bean의 어떤 메소드가 어떤 값이 입력 되면 어떤 값이 리턴 되어야 한다는 내용 모두 개발자 필요에 의해서 조작이 가능합니다.

 

요약하면 어떤 입력값이 주어질때 리턴값을 개발자가 조작해 테스트를 하도록 할수 있는것이다 사용하는 이유는 하나의 서비스 메소드를 테스트 하기위해 불필요한 테스트 데이터를 생성해주어야 하기때문이다

 

 

*Mock vs MockBean 차이

 

https://simgee.tistory.com/58

 

mock() vs @Mock vs @MockBean 이제 그만 헷갈리자!

테스트를 수행하다보면, 실제 객체를 대신해주는 테스트용 객체를 생성해 줄 때, mock을 사용하게 됩니다. 이때마다 사용했던 mock() 과 @Mock 그리고 @MockBean 세가지에 대해 정리해보겠습니다. Mockito

simgee.tistory.com

 

요약하면 @MockBean와 @Mock의 차이점은 스프링 애플리케이션 컨텍스트의 로딩 유무에 따라 다르다는 것이다

즉 mock 객체가 스프링 빈에 등록되어야 한다면 @MockBean 아니라면 @Mock을 사용하면된다

 

*참고 

스프링 컨테이너 관련 개념

 

https://ittrue.tistory.com/220

 

[Spring] 스프링 컨테이너(Spring Container)란 무엇인가?

본 내용은 온라인 강의 사이트 인프런의 김영한 님의 강의 내용이 포함되어 있습니다. '스프링 핵심 원리 - 기본편' 스프링 핵심 원리 - 기본편 - 인프런 | 강의 스프링 입문자가 예제를 만들어가

ittrue.tistory.com

 

요약하면 스프링 컨테이너엔 두 종류의 인터페이스가 있다 ( BeanFactory , application context)

스프링 컨테이너는 빈팩토리의 기능을 상속 받아 확장한 애플리케이션 컨텍스트를 주로 사용한다

 

Ioc , Di 관련 개념

https://devmango.tistory.com/174

 

[Spring] IoC/DI 란?

IoC(Inversion Of Control, 제어의 역전)는 간단히 프로그램의 제어 흐름 구조가 뒤바뀌는 것이라고 할 수 있다. 즉, 모든 종류의 작업을 사용하는 쪽에서 제어하는 구조를 거꾸로 뒤집는 것이다. 오브

devmango.tistory.com

 

https://lucas-owner.tistory.com/39

 

[Spring] Spring-Container, IoC, DI, Singleton 개념 정리

목차 IoC 란? Spring Container (스프링 컨테이너) DI(Dependency Injection) 란? Singleton 패턴이란? IoC 란? IoC 란 Inversion Of Control의 약자이며, 제어의 역전 이라고 한다. 프로그래머와 프레임워크의 주체가 바뀌

lucas-owner.tistory.com

 

요약하면 Ioc가 적용된 대표적인 기술은 프레임워크이다 (내가 작성한 코드가 직접 제어의 흐름에 담당한다면 라이브러리)

Ioc의 역할을 담당하는 것이 스프링 컨테이너이다

 

4. @Builder

https://inpa.tistory.com/entry/GOF-%F0%9F%92%A0-%EB%B9%8C%EB%8D%94Builder-%ED%8C%A8%ED%84%B4-%EB%81%9D%ED%8C%90%EC%99%95-%EC%A0%95%EB%A6%AC

 

💠 빌더(Builder) 패턴 - 완벽 마스터하기

Builder Pattern 빌더 패턴(Builder Pattern)은 복잡한 객체의 생성 과정과 표현 방법을 분리하여 다양한 구성의 인스턴스를 만드는 생성 패턴이다. 생성자에 들어갈 매개 변수를 메서드로 하나하나 받아

inpa.tistory.com

 

https://velog.io/@rlvy98/Spring-Lombok-Builder%EB%9E%80

 

[Spring] Lombok @Builder란?

Spring을 가지고 프로젝트를 진행하는 과정에서 객체를 생성할 때 간편하게 Lombok을 활용해 @Builder를 사용했습니다. 하지만 @Builder가 어떻게 구성되어있는지 궁금했기에 학습을 통해 다음 어노테

velog.io

 

 

아래 내용은 두번째 링크 내용이다

 

@Builder 어노테이션을 클래스에 적용하면 해당 클래스에 대한 빌더 클래스를 자동으로 생성합니다. 이 빌더 클래스는 객체의 생성과 속성 설정을 담당하며, 메서드 체인을 통해 속성 값을 설정할 수 있습니다.

 

빌더 패턴을 통해 가질수 있는 이점은 유연한 객체 생성, 가독성과 유지보수성, 불변 객체 생성, 선택적 매개변수 처리 등이 가능하다

 

*@Builder 와 @ NoArgsConstructor 어노테이션을 같이 사용할때 @AllArgsConstructor가 있어야 하는 이유 : 

@Builder는 기본적으로 모든 멤버 변수를 파라미터로 받는 생성자가 필요하다 그 이유는 build() 메소드에서 앞서 말한    생성자를 통해 리턴 해야하기 때문이다 그런데 @Builder는 생성자가 없으면 모든 멤버 변수를 파라미터로 받는 생성자를 생성하고, 없으면 따로 생성자를 생성하지 않는다 @ NoArgsConstructor 어노테이션을 통해 생성자가 있는 상태이기 때문에 @Builder는 모든 멤버 변수를 파라미터로 받는 생성자를 생성하지 않게 되기 때문에 에러가 발생한다

 

참고링크

https://velog.io/@maketheworldwise/Builder-AllNoArgsConstructor-%EC%A0%9C%EB%8C%80%EB%A1%9C-%EC%95%8C%EA%B3%A0-%EC%82%AC%EC%9A%A9%ED%95%98%EC%9E%90

 

@Builder, @All/NoArgsConstructor 제대로 알고 사용하자!

USE BUILDER ANNOTATION PROPERLY

velog.io

 

5. ArgumentCaptor

//given
AccountUser user = AccountUser.builder()
        .id(12L)
        .name("Pobi").build();
given(accountUserRepository.findById(anyLong()))
        .willReturn(Optional.of(user));
given(accountRepository.findFirstByOrderByIdDesc())
        .willReturn(Optional.of(Account.builder()
                .accountNumber("1000000012").build()));
//1.
given(accountRepository.save(any()))
        .willReturn(Account.builder()
                .accountUser(user)
                .accountNumber("1000000013").build());
//2.
ArgumentCaptor<Account> captor = ArgumentCaptor.forClass(Account.class);
//when
AccountDto accountDto = accountService.createAccount(1L, 1000L);
//then
//3.
verify(accountRepository, times(1)).save(captor.capture());
assertEquals(12L,accountDto.getUserId());
//4.
assertEquals("1000000013", captor.getValue().getAccountNumber());

 

현재 accountNumber가 저장될때 가장 마지막 accountNumber 에서 1씩 증가한 값이 저장이 되고 있다 그걸 확인 할수 있는 방법이 ArgumentCaptor를 사용하는 방법이다

 

 1. 어떤 accountNumber를 저장(save)하는지 확인하기위해 ArgumentCaptor 사용

 2. accountRepository가 저장하는 것은 account즉 타입은 account

 3. 저장하는 횟수는 1번임을 검증하고 그 때 저장하는 값(account)을 캡쳐

 .4 캡쳐한 값(accountNumber)을 검증

 

 

6. successDeleteAccount 테스트 코드 에러

테스트 코드 작성했는데 cannot deserialize from object value 라는 에러가 발생해 구글링을 통해 아래 관련 링크 참고했다

https://azurealstn.tistory.com/74

 

cannot deserialize from object value 에러!

cannot deserialize from object value (no delegate- or property-based creator) 위와 같은 에러가 발생했다면 아래글을 한번 확인해보자. Member Class 먼저 데이터를 담을 모델을 정의하였습니다. //Getter, Setter는 생략 p

azurealstn.tistory.com

 

원인은 JSON 데이터를 Java Object로 변환하기 위해서 비어있는 생성자가 필요했지만 jackson library는 빈 생성자가 없는 모델을 생성하는법을 모르기 때문이다 따라서 직접 빈 생성자를 추가해도 되고 @NoArgsConstructor 어노테이션을 추가해 해결할수 있다 

 

 

7. 컨트롤러 URL 매핑 오류 

Failed to load ApplicationContext : Error creating bean with name 'requestMappingHandlerMapping' defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'transactionController' method 

 

확인해보니 컨트롤러의 URL을 같게 설정해주어 발생한 오류였다 아마 컨트롤러의 코드를 작성할때 복붙을 사용하다보니 만나게 된것같다.. ;

'프로젝트' 카테고리의 다른 글

매장 예약 - Redis 캐시 적용  (0) 2024.02.22
매장 예약 서비스 - 동시성 문제  (0) 2024.02.19
매장 예약 서비스 - Spring Jpa 연관 관계  (0) 2024.02.18
배당금 프로젝트  (1) 2024.01.31
날씨 일기 프로젝트  (0) 2024.01.27