Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test: use fixture #38

Merged
merged 21 commits into from
Aug 27, 2024
Merged

Test: use fixture #38

merged 21 commits into from
Aug 27, 2024

Conversation

goldentrash
Copy link
Contributor

@goldentrash goldentrash commented Aug 23, 2024

  • 멤버 등록에 필수 속성을 추가했습니다. (Role, Department etc...)
  • Controller Test에 관리자 권한이 필요한 경우 미리 반영했습니다.
    • Security 속성 반영은 개발 끝나면 일괄 적용하는게 나을듯 합니다
  • Test Fixture 작성, 적용
    • domain/external/의 테스트는 Test Data가 명시적으로 드러나는게 좋다 생각해서 Fixture 적용 안 했습니다
    • controller/application/은 대부분 해당 method의 동작 및 반환에 Test Data의 상세 내용이 중요하지는 않다고 생각했습니다.
  • Controller Test를 단위 테스트로 전환
    • Spring Security Form Login은 Security 테스트하는거라 생각해서 통합 테스트 유지했습니다.
    • 테스트 총 러닝 타임은 생각보다 안 줄더군요

@goldentrash goldentrash added the enhancement New feature or request label Aug 23, 2024
@goldentrash goldentrash self-assigned this Aug 23, 2024
Copy link
Collaborator

@ekgns33 ekgns33 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오.. 고생하셨습니다.
내용이 많은데 공통적으로 고민이 되는 것들만 적어볼게요.

  1. 지금까지 서비스 레이어도 테스트코드를 작성했었는데 컨트롤러테스트를 하면 서비스레이어의 테스트코드가 필요한지 고민입니다. 도메인단과 통합테스트만으로 충분한 것 같기도하네요.

  2. 오류를 뱉는 테스트들에 대해서 불필요한 값들이 들어간 테스트가 보이기도 합니다. Not Null과 같은 제한때문에 집어넣은 객체들에 대해서는 어쩔 수 없다고 생각이 드는데 테스트할 대상만 빌더를 통해 생성해야할 것 같아요.

ex) 이미 존재하는 멤버 확인 << 멤버 email만 필요.

  1. Fixture를 이렇게 사용해본적은 없는 지라 저도 잘 모르겠습니다ㅠㅠ 😢 . 그런데 서비스 레이어의 코드를 걷어낸다고 생각하고 컨트롤러와 도메인만 두고 생각해볼게요. 중복되는 객체를 정리하는 것은 필요해 보이지만 컨트롤러테스트에서 getEventFixture1()과 같이 객체를 사용하는 데에 저는 부정적으로 바라봅니다.

제가 생각한 이유는 이러해요.

  1. 중복되는 값이라면 테스트 클래스상단에 정의한다.
  2. 테스트코드를 읽을때 봐야할 레이어가 하나 더 생긴다. 파일을 들어가서 이 게터가 어떤 객체를 반환하는지 봐야하기 때문이죠. (결국 피로하다...라는 문제입니다.)

Copy link
Contributor Author

@goldentrash goldentrash left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

요약

  • Fixture Factory가 테스트 목적과 관계가 있는 속성만을 입력받도록 Factory를 분리하면 괜찮지 않을까요?
  • /application 테스트를 걷어내고 통합 테스트로 전환하더라도 RestDoc을 위한 단위 테스트는 별도로 작성했으면 합니다.

리뷰 답변

우선, 상당히 큰 PR이었는데 정성 들여 검토해 주셔서 감사합니다. 역시 테스트는 어렵네요. 짚어주신 내용들 모두 공감하고 있습니다.

저 역시 테스트는 WET하게, Verbose하게 작성해야 한다고 생각합니다. 언급해 주신 것처럼 테스트가 실패할 경우 원인 분석이 빨라야 한다고 생각해요. 테스트 실패의 원인이 테스트 Case 내부가 아닌 외부(Fixture)에 있다면 원인 파악에 어려움이 따르겠죠. (이만저만 피로한게 아닐겁니다) 뿐만 아니라, 외부 Fixture를 사용하다간 자칫 테스트 Case 간 응집이 강해져 테스트 하나의 변경이 주변 테스트로 전파될 위험도 분명히 존재합니다.

그렇기에 제가 이런 PR을 작성하게 될 것이라고는 생각하지 못했는데, 작성하면서 저 스스로도 신기하고 이게 정말 맞는지 고민이 많이 되더군요. 그럼에도 불구하고 테스트 Fixture를 분리해야겠다 마음먹은 이유가 있었습니다.

Fixture가 필요하다고 생각하는 이유

  1. 불필요한 정보 과다로 오히려 테스트 의도가 묻힘
  2. 테스트 작성 과정에서 충분히 다양한 Data를 떠올리기 어려움 (특정 Case 누락 발생)

(각 사안 예시는 아래에 별도로 작성해 두겠습니다)

Fixture를 사용하기로 했다면 이제 2가지 문제가 따라오게 되지요.

  1. Fixture를 어떻게 구성하고, 불러올(사용할) 것인가?
  2. Fixture를 어디에 사용할 것인가?

Fixture를 어떻게 구성할 것인가? -- External Static Factory

1번 고민에 대해서는 별도 Factory 클래스로 분리하는 방향을 생각했습니다. 테스트 클래스 자체로 private factory나 private instance를 작성하는 방향을 언급해 주셨는데, 개인적으로는 이미 Fixture를 사용하는 시점에서 피로도의 차이는 크지 않다고 생각합니다. 테스트 클래스 상단이든, Before/After Setup 블럭이든 어차피 테스트 블럭을 벗어나야 Fixture 내용을 확인할 수 있는 것은 동일하니까요.

그러한 이유로 External Static Factory를 작성했는데, kotlin이나 js와 달리 java는 method에 default parameter를 지원하지 않기에 Fixture Factory가 모든 인자를 받아오게끔 하거나, 필요한 인자마다 factory를 분리해야 했습니다.

첫 번째의 경우에는 기존과 다를 것이 없고, 두 번째 경우에는 메서드 분기가 너무 과해지지 않을까 생각했습니다. 그래서 고민 끝에 "메서드 이름에 해당 Fixture의 의도가 분명히 드러나면 충분하지 않을까...?"란 결론에 도달했습니다만

예, 제 판단 미스였던 것으로 보입니다. 언급하신 것처럼 getEventFixture1으로는 충분한 정보가 전달되지 않습니다.

오류를 뱉는 테스트들에 대해서 불필요한 값들이 들어간 테스트가 보이기도 합니다. Not Null과 같은 제한때문에 집어넣은 객체들에 대해서는 어쩔 수 없다고 생각이 드는데 테스트할 대상만 빌더를 통해 생성해야할 것 같아요.

결국 검증하고자 하는 인자만으로 Fixture를 생성하는 Factory를 만드는 것이 가장 좋은 방법이 아닐까 생각합니다. 예시로 이미 작성한 getEmailTaskFixtureWillSendAfterXSeconds가 있겠네요.

Fixture를 어디까지 사용해야 하는가?

원래는 RestDoc 테스트에만 적용할 생각이었습니다. RestDoc Test는 어떠한 기능에 대한 Functionality를 테스트하기보다는, 요청응답 간의 Payload Scheme을 확인하는 문서로서의 기능이 더 커 보입니다. 때문에 객체의 값 속성 하나하나는 크게 중요하지 않다고 생각했어요.

그래서 실제로 /domain/external에 위치한 단위 테스트에는 Fixture를 적용하지 않았습니다. 다만 고민은 /application에 위치한 테스트였습니다. 처음 계획할 때는 Fixture 적용 대상이 아니었지만, 이미 Fixture Instance (like mock1)를 적용한 상태였기에, 일괄 적용했습니다.

예, 이 부분 역시 아쉬운 판단으로 보입니다. RestDoc Test와 다르게 Application 테스트는 실제 비즈니스 로직의 동작을 검증합니다. 때문에, 입력과 출력값의 속성이 매우 중요합니다. 현 Fixture Factory로는 해당 속성이 충분히 가시적으로 드러나지 않습니다. 다만 이 문제는 위에서 언급했던, 필요한 속성별로 factory를 분리한다면 어떨까 싶습니다. 다시 한번 getEmailTaskFixtureWillSendAfterXSeconds를 주목해 주세요.

RestDoc 테스트는 조금 독특한거 같습니다...?

지금까지 서비스 레이어도 테스트코드를 작성했었는데 컨트롤러테스트를 하면 서비스레이어의 테스트코드가 필요한지 고민입니다. 도메인단과 통합테스트만으로 충분한 것 같기도하네요.

우선 해당 내용에 동의합니다. 다만, RestDoc을 사용한다면, 문서를 위한 테스트는 통합 테스트가 아닌 단위 테스트였으면 합니다.

문서는 API 당 하나의 Case만 있으면 되지 않나 싶습니다. 다양한 응답 예제가 필요하다면 테스트 Case를 늘리기보다는 하나의 응답에 다양한 객체가 포함되도록 하면 되지 않을까요? 가령 이벤트 목록 조회에 출석이 있는 이벤트와 출석이 없는 이벤트가 모두 포함되도록요. 물론 BadRequest와 같이 요청이 달라지는 경우에 대해서는 다른 Test Case가 필요하겠지요.

즉, "서비스 레이어 테스트를 걷어내고, 통합테스트와 도메인 단위테스트로 전환"하는데 동의합니다. 다만 이 경우 RestDoc을 통합테스트를 통해 생성하는 대신, RestDoc 작성만을 위한 별도 클라이언트 단위 테스트도 작성하는게 좋다고 생각합니다.

@@ -28,184 +29,129 @@ class EmailServiceTest {

private EmailService subject;

private final EmailTask mock1 =
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixture를 Service Test에도 적용하기로 결정한 이유

원래 Service Layer에는 Fixture를 사용하지 않으려 했었는데, 이미 적용 중인 부분이 있어 일괄 적용했습니다.

@@ -135,35 +112,24 @@ void should_get_all_events_when_request() throws Exception {
fieldWithPath("data.eventBriefs[].title").description("이벤트 제목"),
fieldWithPath("data.eventBriefs[].content").description("이벤트 내용"),
fieldWithPath("data.eventBriefs[].startAt").description("이벤트 시작 시간"),
fieldWithPath("data.eventBriefs[].thumbnail").description("썸네일 URL"))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixture 사용 이유 - 필요한 Case 누락이 쉬움

기존 Test Data에는 썸네일이 누락된 경우가 포함되지 않았습니다. 결과적으로 Optional 한 payload가 늘 있어야만 하는 것처럼 문서화되었어요.

실제로 (물론 기획과의 소통이 더 원활했더라면 발생하지 않았겠지만) 프런트 팀이 썸네일이 무조건 있어야 한다고 생각하고 이벤트 세션 등록에 반드시 하나 이상의 이미지를 등록하도록 강제하는 경우도 있었습니다.

.title("test event3")
.content("test event content")
.startAt(LocalDateTime.now())
.thumbnail(new URL("https://foo.com/bar/baz.jpg"))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixture 분리가 필요하다 생각했던 시점

불필요한 정보 과다로 오히려 테스트하고자 하는 내용이 눈에 들어오지 않음

.totalAttendances(3L)
.actualAttendances(2L)
.attendanceInfoList(
List.of(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixture 분리를 마음먹은 시점 2

@goldentrash
Copy link
Contributor Author

제 의견에 대한 생각이 궁금하네요 @ekgns33
만약 긍정적으로 생각하신다면, Factory가 테스트 목적이 되는 인자만 받도록 분기하는 방향으로 커밋을 올리겠습니다.
서비스 레이어 테스트의 통합테스트 전환은 별도 PR로 관리해야 한다고 생각해서 이 PR에 추가 커밋을 하지는 않겠습니다.

@ekgns33
Copy link
Collaborator

ekgns33 commented Aug 24, 2024

역시 이런 큰 고민이 있었군요 😢
읽고 저도 고민을 해봤습니다! 제가 생각한 바로는

1. RestDocsTest와 컨트롤러 테스트를 분리하자. (매우동의)

이름에 걸맞은 문서화를 위한 테스트와 우리가 테스트하고자하는 유즈케이스를 테스트하는 코드는 분리하는게 맞아보이네요

2. Fixture 클래스가 모든 값을 들고있기보다는 팩토리메서드를 두고 필요한 값을 주입받도록하자.

예, 이 부분 역시 아쉬운 판단으로 보입니다. RestDoc Test와 다르게 Application 테스트는 실제 비즈니스 로직의 동작을 검증합니다. 때문에, 입력과 출력값의 속성이 매우 중요합니다. 현 Fixture Factory로는 해당 속성이 충분히 가시적으로 드러나지 않습니다. 다만 이 문제는 위에서 언급했던, 필요한 속성별로 factory를 분리한다면 어떨까 싶습니다. 다시 한번 getEmailTaskFixtureWillSendAfterXSeconds를 주목해 주세요.

허나 상황마다 팩토리메서드를 다만들자는 의미는 아닙니다.
유즈케이스마다 모든 fixture를 구현하게되면 변경에 너무 취약한 코드가 될 것 같아요.

  • 개인적인 선호인 것 같지만 저는 서비스레이어 내의 매핑객체가 아니라 RequestBody를 의미하는 Request객체라면 필드를 명시해서 보여주는게 더 알아보기 쉬운 것 같아요.

뭔가 테스트의 범위 내에서 이렇게 명시하는게 전 보기가 편하더라구요. Json이 머리에 생각되는...

EventFixture.createFixtureWithTime(1000)

EventTask.builder()
  ...
  .delay(1000)
  .build();

이건 제 개인취향입니다 ㅎㅅㅎ 😆

그러한 이유로 External Static Factory를 작성했는데, kotlin이나 js와 달리 java는 method에 default parameter를 지원하지 않기에 Fixture Factory가 모든 인자를 받아오게끔 하거나, 필요한 인자마다 factory를 분리해야 했습니다.

코틀린에서 defualt parmater가 있었다면 저희는 걱정을 할 것이 줄어들 수도 있었겠죠! 허나 그렇지 않기에 빌더패턴과 비슷한 형태로 직접 만들어야하지 않을까 생각이됩니다. (근데 이러면 빌더를 사용하는 것과 뭐가 다를까요.)

@goldentrash
Copy link
Contributor Author

goldentrash commented Aug 25, 2024

허나 상황마다 팩토리메서드를 다만들자는 의미는 아닙니다.
유즈케이스마다 모든 fixture를 구현하게되면 변경에 너무 취약한 코드가 될 것 같아요.
개인적인 선호인 것 같지만 저는 서비스레이어 내의 매핑객체가 아니라 RequestBody를 의미하는 Request객체라면 필드를 명시해서 보여주는게 더 알아보기 쉬운 것 같아요.

그렇다면 아래와 같은 방향은 어떨까요 @ekgns33 ?

@Getter
public class MemberFixture {

  Member fixture;

  @Builder
  public MemberFixture(Long id, String memberId, String password, String name, String email, String department, MemberRole role){
    this.fixture = Member.builder()
      .id(getDefault(id, 0L))
      .memberId(getDefault(memberId, "202400000"))
      .password(getDefault(password, "$2a$10$d7DjseDroHsRGVGR1zDUL.q7uwAQ2aH4nHM1JiQ1OFV.D0qUTl7w."))
      .name(getDefault(name, "member"))
      .email(getDefault(email, "[email protected]"))
      .department(getDefault(department, "Computer Science"))
      .role(getDefault(role, MemberRole.MEMBER).toString())
      .batch(getDefault(BATCH, "24-25"))
      .build();
  }

  private static <T>T getDefault(T value, T defaultValue){
    return value == null ? defaultValue : value;
  }
}
// given
Member memberToRegister = MemberFixture.builder().id(1L).memberId("202400001").build().getFixture();

Builder의 형태를 유지시키면서도 필요한 속성만 설정하고 나머지는 기본값을 사용합니다. 이렇게 할 경우 실 Domain 객체에서 기본값을 사용할 수 없는 속성(memberId, password etc)도 테스트를 위해 기본값을 적용할 수 있습니다.

Copy link

sonarcloud bot commented Aug 27, 2024

@goldentrash goldentrash merged commit 0d4cf21 into develop Aug 27, 2024
2 checks passed
@goldentrash goldentrash deleted the test/use-fixture branch August 27, 2024 08:56
goldentrash added a commit that referenced this pull request Aug 27, 2024
* test: Fixture 작성 (`Member`, `Event`)

* change: 멤버 등록 필요 속성 수정

* change: `WithCustomUser` Annotation을 사용하도록 통일, 관리자 권한이 필요한 API일 경우 해당 권한 테스트에 미리 반영

* test: `MemberFixture` 적용

* test: GWT 다듬기

* style: `EmailDetails`가 Entity가 아닐 경우 단일 Data인 점을 반영하여 `EmailDetail`로 이름 변경

* test: Email Fixture 작성

* test: Email Fixture 적용

* style: `given`절의 메서드가 when보다는 given을 사용하도록 변경

* test: `Attendance` Fixture 작성

* test: `Attendance` Fixture 적용

* test: `Event` Fixture 작성

* test: `Event` Fixture 적용

* test: `Controller` Test를 단위 테스트로 전환

* test: EmailFixture 적용

* fix: 이미 인증된 사용자를 통해 로그인 테스트를 하던 문제 해결

* change: 멤버 출석 성공 시 보여주는 정보 축소

* change: 멤버 출석 등록 시 `Role`을 받도록 수정

* feat: feedback 반영, Test Fixture를 좀 더 Verbose 하게

* test: 변경한 Fixture 반영

* chore: test build에 lombok 사용
goldentrash added a commit that referenced this pull request Aug 27, 2024
* Test/test ci (#2)

* Gitactions Test (#1)

* feat : 소나큐브 플러그인 의존성추가

* fix: 그래들 파일 수정

* feat: CI용 워크플로우생성

* feat : 테스트용 커밋

* fix: 잘못된 디렉토리명 수정

* feat : CI실패 시 디스코드 알림 추가

* test : CI 테스트를 위한 커밋

* feat: 그래들 캐시 추가, 불필요한 스크립트 제거

* Bp 3 spring project  (#3)

* chore : h2, p6spy의존성 추가

* feat : 응답을 위한 클래스 생성

* feat : 에러코드 공통 관리를 위한 Enum생성

* feat : 전역 에러 핸들러 추가

* remove : 불필요한 파일 삭제

* feat : 워크플로우 수정

* feat : 생성자 파라매터 수정, Of 메소드 수정

* Bp 4 swagger configuration (#4)

* chore : RestDocs, Swagger 의존성추가

* feat : 테스트용 컨트롤러 작성

* feat : RestDocsTest 어노테이션 생성

* test : 스웨거 컨트롤러를 위한 테스트 코드 작성

* Bp 12 implement user login (#5)

* chore : 스프링 시큐리티, 테스트 모듈 추가

* Feat : 스프링 시큐리티를 위한 UserDetail기능 재작성, 핸들러 작성

* feat : 전역 에러 핸들러에 비즈니스 에러 핸들러 추가

* feat : 비즈니스 로직에서 발생하는 예외를 정의하는 클래스 정의

* feat : 사용자 인증관련 에러코드 추가, 응답클래스에 메소드 추가

* refactor : 사용하지 않는 클래스 의존 삭제

* test : 로그인 기능 테스트 코드 작성

* remove : 필요없는 파일 삭제

* feat : 유저 권한 Enum클래스와 로그인 시 권한을 부여하는 기능 추가

* feat : 멤버 엔티티, 레포지토리 생성

* test : 로그인 통합 테스트 작성

* hotfix : 불필요한 파라매터설정 제거

* fix : 코드리뷰 적용 csrf 적용 및 스프링시큐리티로 세션저장 활성화

* refactor : 불필요한 상태값 제거에 따른 타입 변경

* Bp 24 implement user crud (#9)

* Bp 25 implement user registration (#6)

* feat : 회원가입 api 권한 수정, 엔드포인트 prefix 메소드 추가

* feat : 에러코드, 커스텀 에러 추가, 전역 핸들러에 로직구현

* feat : 회원가입 DTO추가, 멤버 컨트롤러 추가

* feat : 멤버 서비스 추가, 회원가입 기능 추가

* test : 컨트롤러 테스트, 유닛테스트 작성

* feat : 유저 비밀번호 암호화 추가

* rename : 파일 위치 수정

* test : 암호화 로직 추가

* rename : DTO 컨트롤러 패키지로 이동

* refactor : 매직넘버 삭제, HttpStatus사용

* refactor : 기존 ErrorCode를 인터페이스화, 도메인마다 에러코드 정의

* refactor : 에러코드 구조 변경에 따른 코드 수정

* chore : spring-validation 추가

* Bp 26 implement user withdraw (#8)

* feat : 객체 생성 시 필드 체크를 위한 Validator생성

* feat : 멤버 엔티티객체 필드 기본값 수정, 탈퇴로직 구현

* feat : 회원 탈퇴 로직 구현

* feat : 시큐리티 회원가입, 로그인 csrf해제

* feat : 시큐리티 유틸성 클래스 추가

* feat : 멤버 서비스 예외 추가와 에러코드 추가

* style : 코드 포맷 수정

* test: 테스트코드 수정, 삭제 테스트코드 작성

* feat : Spring Validation에서 발생하는 에러 핸들링

* test : mock user 어노테이션추가

* refactor : 코드리뷰 적용

* fix ; csrf 비활성화

* feat : 식별자 전략 명시 IDENTITY

* Bp 14  attendance api (#7)

* feat: Event 엔티티 생성

* feat: 특정 달의 이벤트 목록 조회

* feat: Participants 엔티티

* feat: 출석 기능 (Google Oauth 부분은 뼈대만)

* feat: Event Controller 작성 및 테스트, 문서 생성

* chore: validator와 Oauth Client 추가

* feat: Google OIDC를 이용한 사용자 출석 (draft)

* feat: 이벤트 출석 등록 -> 출석 URL (for QR Code) 생성

* comment: TODO, 출석 만료 기능 필요

* fix: 출석 API를 GET으로 변경, security matcher 수정 및 request 유지

* feat: security config conflict 정리

* feat: validation 책임을 Entity가 아닌 Factory로 전가

* feat: dto를 service layer가 아닌 presentational layer에서 정의

* feat: Event 도메인의 Custom ErrorCode와 Exception 정의

* style: `@RequiredArgsConstructor` 활용

* style: gwt 다듬기

* chore: 실 credential 반영

* fix: presentational layer test에 `@SpringbootTest`를 사용하도록 일괄 변경

* fix: HTTP METHOD 정정 (post -> get)

* feat: QR Login 구현

* chore: build 실패시 artifact로 report 보관

* fix: spring build directory 정정

* fix: CI, application.yml profile 맞춤

* fix: CI, yml 문법

* chore: jacoco 추가

* fix: jacocoTestReport

* Bp 35 implement email sending (#10)

* chore : Spring-mail 의존성 추가

* feat : 이메일, 수신자 엔티티, 레포지토리 생성

* feat : Email전송 컨트롤러 작성

* feat : 이메일서비스 작성

* feat : 이메일 전송 클라이언트 설정, 전송 로직작성

* test : 컨트롤러 테스트 작성

* format : reformat codes indentation 2space로 수정

* feat : 클래스 이름 수정, 연관관계 매핑

* feat : toEntity생성, 적용

* rename : 네이밍 수정

* refactor : 컨벤션에 맞게 의존성 변경

* feat : 기본 트랜잭션 설정 read only로 명시

* refactor : 불필요한 import 제거

* feat : 에러 처리 분기 수정

* test : 이메일 기능 테스트코드 작성

* Bp 27  출석현황조회 api (#11)

* feat: 학과 필드 추가

* feat: `AttendanceInfo` DTO, query 구현

* feat: 출석 현황 조회 Controller & Test

* feat: 출석 현황 조회 Service

* feat: `AttendanceInfo`에 participantId field 추가

* fix: 출석 현황 조회에 멤버 외의 인원이 출석한 경우 error가 발생하지 않도록 수정

* feat: 멤버 출석 현황 수정 기능

* feat: 멤버 출석 현황 수정 controller 작성 및 test

* fix: DTO 전환 과정에서 immutable list로 초기화되어 이후 수정이 불가능했던 문제 해결

* fix: 유효하지 않은 `participantId`의 출석 수정 요청 exception handling

* fix: Event에 이미 출석이 존재할 경우, 중복 생성을 막음

* chore: gradle task `openapi3`, type casting

* style: `MemberToParticipantMapper`에서 `ParticipantMapper`로 이름 변경

* feat: 출석 현황 수정 request payload 형식 변경

* refactor: `Member` To` Participant` Mapping 과정에서 `Member`에 존재하지 않던 `attendance` field를 기본으로 false로 설정

* Bp 36 implement email cancellation (#14)

* feature : EmailTask로 네이밍 변경, VO 생성

* remove : 엔티티이름 변경에 따른 클래스 삭제

* feat : 이메일작업 레포지토리생성

* feature : 이메일 작업등록 관련 에러, 에러코드 추가

* feature : 이메일 작업 수정, 조회, 삭제 로직 추가

* feature : DTO와 Mapper 작성

* test : 컨트롤러 테스트 작성

* feat : 이메일 서비스 작성, 헬퍼 클래스 추가

* test : 이메일 서비스 코드 추가

* refactor : 팀 컨벤션 적용

* refactor : 생성자 접근 범위 조정

* refactor : 엔티티 이름 변경에 따른 수정

* test : 테스트코드 수정

* rename : 이메일 클라이언트에서 발생하는 에러코드로 이름 수정

* test : EmailTask 테스트코드 작성

* Bp 38 retrospect crud api implementation (#12)

* feat: 이벤트 및 회고 등록 기능

* feat: 이벤트 등록 controller 작성 및 테스트

* feat: 이벤트 회고 조회 기능

* feat: 이벤트 회고 조회 controller & 테스트

* feat: 이벤트 회고 수정 기능

* feat: 이벤트 회고 수정 controller 및 test

* refactor: `Retrospect`를 `Event`의 Embedding으로 변경

* fix: `@Valid`를 통한 dto 검증 추가

* Bp 39 implement email scheduler (#15)

* feat : 미전송 작업 조회, 작업완료 메소드 추가

* feat : 미전송 작업 쿼리 추가

* feat : 스케줄러 설정파일 작성

* feat : 작업 정보 메모리 저장소 작성

* feat : 작업 조회 관련 에러 및 코드 추가

* feat : 작업 스케줄러 추가

* feat : DTO에서 entity로 파라매터 수정

* feat : 스케줄 관련 업데이트 적용

* feat : 이메일 전송 로그 추가

* test : 이메일 스케줄 서비스 테스트코드 작성

* refactor : unused import 삭제

* test : 이메일 스케줄링 통합테스트 작성

* feat : 작업 스케줄 서비스 추가

* test : 로직 수정 테스트코드에 반영

* style : 카멜케이스 적용

* feat : 에러코드 정의 변경

* feat : cancel중 다른 스레드 접근 불가능하게 락 적용

* refactor : 함수 네이밍 변경

* refactor : remove save() method

* rename : EmailScheduleServiceTest 이름 수정

* feat : 디스코드 알림 웹 훅을 위한 클라이언트 작성

* feat : RestTemplate 설정파일 작성

* feat : 디스코드 문자열 상수 정의

* feat : 이메일 전송 에러처리 추가

* rename : 위치 수정

* test : 이메일 전송 실패시 디스코드 알림 테스트 추가

* refactor : 에러를 받아서 디스코드 메세지를 만드는 로직을 디스코드 메세지에서 작성

* test : 디스코드 메세지 테스트 작성

* refactor : 반드시 발생하는 상황 finally로 실행부분 변경

* fix : 이메일 저장후 바로 조회 시 조회가 안되는 이슈 수정 (#16)

* fix : 이메일 저장후 바로 조회 시 조회가 안되는 이슈 수정

* fix : 사용하는 메소드 수정에 따른 test코드 모킹 변경

* Bp 37 event crud api implementation (#13)

* chore: aws-s3 모듈 추가

* feat: s3 presigned url 기능

* feat: 당장 불필요한 Member Profile Image 주석처리

* change: 이달의 출석 조회를 `EventController`에서 `AttendanceController`로 이동

* feat: S3 Storage Client

* feat: `EventImages`

* feat: 불필요한 파일 삭제 (`ImageController/Service`)

* feat: `Event` CRUD 기능

* feat: `Event` CRUD Controller

* fix: 일대다 Mapping에서 변경이 전파되도록 수정

* fix: 이미지 URL을 반환하도록 변경

* fix: 이벤트 상세 조회에 Image key를 반환하도록 수정

* fix: 사진 추가를 Optional하게 변경

* fix: 잘못된 에러 메시지 수정 + object key에 확장자 포함

* fix: Spring Security Matcher가 정상 동작하도록 변경 (출석 Entry 수정)

* fix: Spring Security Matcher가 정상 동작하도록 변경 (출석 Entry 수정)

* test: 회원 출석 url 변경 반영

* test: 누락되었던 인증 정보 추가

* test: 이벤트 CRU 테스트

* style: redundant 삭제

* refactor: 혼동을 줄이기 위해 `equals` override

* refactor: 혼동을 줄이기 위해 `equals`를 `isKeyEqual`로 변경

* feat: S3 object URL에 object key가 포함되어 있음!!

* refactor: DTO에 생성 위임

* style: rename(`S3Config` -> `S3Properties`)

* refactor: String format으로 + 연산 줄이기

* fix: S3 property를 제대로 읽어오도록 수정

* fix: 모든 Event 조회에 N+1 문제 해결

* Fix redefine email receivers (#17)

* fix : 이메일 개수가 증가할 시 제한에 걸리는 이슈로 컬렉션 테이블 분리

* feat : 트랜잭션 템플릿으로 새로운 트랜잭션 생성 및 롤백

* fix : Resttemplate Post요청시 URI타입 캐스팅

* Fix: 로그인 성공 후 스태틱 페이지가 없어 발생하는 에러 수정 (#18)

* fix: 로그인 성공 후 스태틱 페이지가 없어 발생하는 에러 수정

* fix: test가 3xx가 아닌 200을 기다리도록 수정

* fix: test가 redirection url을 기대하지 않음

* Fix: error response (#21)

* fix: `BusinessException`을 response 할 때, name 대신 `logMessage`를 반환하던 문제 해결

* fix: 4xx 대신 5xx를 반환하던 문제 해결

* fix: fallback handler의 인자를 `RuntimeException`에서 `Exception`으로 변경

* Fix jpa element collection type (#20)

* fix : List에서 Set으로 자료구조 변경

* feat : EmailReceviers 자료구조 변경 적용

* feat : Set 삭제, 추가 메소드

* feat : 변경전 수신자들과 비교하는 함수 추가

* feat : 시그니처 변경 및 타입수정

* feat : 업데이트된 수신자와 기존 값 비교후 병합메소드 추가

* refactor : optimize imports

* test: 이메일 작업 전송대상 업데이트 필터링 테스트

* Fix: `not found` and `login failure` response (#22)

* fix: 404 응답이 500으로 가던 문제 해결

* fix: 로그인 Content-Type이 `x-www-urlencoded`가 아니어서 회원 정보가 제대로 전달되지 않는 경우의 에러 코드 변경

* fix: 로그인 실패 테스트 입력이 의도와 달랐던 문제 해결

* fix: [dev] CORS 비활성화 (#23)

* feat: 사용자가 로그인 된 상태인지 확인하는 API (#24)

* fix: API에 인증받지 않은 사용자가 요청 시 302 대신 401로 반환하도록 수정 (#25)

* fix: 이벤트 이미지가 없을 경우 이벤트를 조회할 수 없던 문제 해결 (#26)

* fix: 이벤트에 누락된 속성(`장소`) 추가 (#27)

* Refactor attendance api (#28)

* Change: include retrospect into event detail (#29)

* change: 이벤트 조회에 이벤트 회고가 함께 조회되도록 변경

* style: DTO 파일 위치 컨벤션 통일

* feat: Event 삭제 API (#30)

* Fix: cors without nginx (#32)

* feat: cors custom filter

* feat: cors custom filter 적용

* fix: cors allowed origin을 `localhost:*`에서 `localhost:5173`으로 변경 (#33)

* fix: preflight시에 security filter chain을 거치기 전에 성공하도록 수정 (#34)

* Change: attendance registration response (#35)

* style: image upload/delete method 분리

* change: 출석 및 출석 URL 생성 응답에 body 추가

* change: 출석 QR 만료 요청에 QR UUID가 불필요하게끔 수정

* test: 수정 사항 반영

* fix: 출석 URI이 제대로 생성되도록 수정

* Feat: include receiver name into mail registration (#31)

* fix: 확률적으로 실패하던 Test Case 보완

* feat: `EmailReceiver`에 이름 정보가 누락되어 있던 문제 해결

* feat: `{이름}`을 통해 대상 이름을 이메일 양식에 포함할 수 있도록 기능 추가

* test: 수정 사항 반영 (이메일 수신자에 이름 속성 추가)

* refactor: 이름 토큰(`{이름}`)을 상수로 정의, 메서드 분리

* test: 이름 토큰(`{이름}`) 치환 동작 확인 테스트 작성

* Feat: request attendance state (#37)

* feat: Attendance Status 조회 API

* test: Attendance Status 조회 API Test

* fix: CORS 재수정 (`List.of` 대신 `Arrays.asList` 사용) + origin에 개발/배포 서버 추가 (#36)

* change: EmailTask 전체 조회시, 응답 양식을 EmailTaskDetail 양식처럼 `ReceiverInfos`를 묶음으로 표시 (#39)

* Test: use fixture (#38)

* test: Fixture 작성 (`Member`, `Event`)

* change: 멤버 등록 필요 속성 수정

* change: `WithCustomUser` Annotation을 사용하도록 통일, 관리자 권한이 필요한 API일 경우 해당 권한 테스트에 미리 반영

* test: `MemberFixture` 적용

* test: GWT 다듬기

* style: `EmailDetails`가 Entity가 아닐 경우 단일 Data인 점을 반영하여 `EmailDetail`로 이름 변경

* test: Email Fixture 작성

* test: Email Fixture 적용

* style: `given`절의 메서드가 when보다는 given을 사용하도록 변경

* test: `Attendance` Fixture 작성

* test: `Attendance` Fixture 적용

* test: `Event` Fixture 작성

* test: `Event` Fixture 적용

* test: `Controller` Test를 단위 테스트로 전환

* test: EmailFixture 적용

* fix: 이미 인증된 사용자를 통해 로그인 테스트를 하던 문제 해결

* change: 멤버 출석 성공 시 보여주는 정보 축소

* change: 멤버 출석 등록 시 `Role`을 받도록 수정

* feat: feedback 반영, Test Fixture를 좀 더 Verbose 하게

* test: 변경한 Fixture 반영

* chore: test build에 lombok 사용

* Docs: readme (#19)

* docs: readme 초본

* docs: Readme에 다이어그램 추가

* [Draft] Release: `v0.0.0` (#40)

* chore: Dockerfile이 app version에 의존적이지 않도록 수정

* chore: spring actuator 추가

* style: `build.gradle` re-format

* chore: 기본 타임존을 한국으로 설정

* chore: API 접속 권한 조정

* fix: OAuth redirect URL scheme을 https로 변경

* fix: 로그인 요청은 로그아웃 상태에서도 허용하도록 변경

* fix: csrf 비활성화 (Client Side 추가 설정 필요)

* chore: CI를 위해, github action이 h2를 사용하도록

---------

Co-authored-by: ekgns33 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants