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

[BE] Feat/#586 핀 수정 시 변경 이력 저장 이벤트 구현 #591

Merged
merged 21 commits into from
Oct 18, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
0bd7c7c
refactor: 테스트 환경 콘솔 로그 출력 설정 추가
yoondgu Oct 16, 2023
e6a4f40
test: 핀 수정 인수 테스트 추가
yoondgu Oct 16, 2023
65ef31b
feat: 핀 수정 시 수정 이력 저장 구현 및 테스트
yoondgu Oct 16, 2023
0dd8fc7
refactor: 사용하지 않는 변수 삭제
yoondgu Oct 16, 2023
19bcc6f
feat: 새 핀 추가시에도 핀 이력 저장
yoondgu Oct 16, 2023
ae2bc06
feat: 핀 수정 이력이 참조하는 엔티티 삭제 시 soft delete 하도록 이벤트 구현
yoondgu Oct 16, 2023
57073b9
feat: 핀 수정 이력은 삭제 개념이 없는 것으로 복구 (이전 커밋 revert)
yoondgu Oct 16, 2023
2a7f4db
test: 핀 수정 이력 이벤트 테스트 실패 수정
yoondgu Oct 16, 2023
a9b5308
test: 빠른 테스트 조건문 확인을 위해 assertAll softly로 변경
yoondgu Oct 16, 2023
9ded478
refactor: hard delete 메서드 Query 작성해서 Modifying 적용
yoondgu Oct 16, 2023
ca92508
rename: PinUpdateHistory 에서 PinHistory로 네이밍 변경
yoondgu Oct 16, 2023
8ed8da4
test: 테스트 displayName 핀 정보 이력 관련 용어 통일
yoondgu Oct 16, 2023
0309e78
fix: 핀 변경 이력 엔티티 컬럼 수정
yoondgu Oct 16, 2023
8444f53
refactor: 불필요한 공백 제거
yoondgu Oct 17, 2023
02519c7
test: 일시 검증 메서드 수정, 핀 변경 일시 검증 추가
yoondgu Oct 17, 2023
20cb321
feat: 핀 변경 이력 엔티티에 핀 변경 일시 컬럼 추가
yoondgu Oct 17, 2023
b257b24
fix: PinHistoryCommandService 트랜잭션 어노테이션 추가
yoondgu Oct 17, 2023
5c1bbdb
fix: 핀 변경 이력 롤백 테스트 예외 수정, 실패 테스트 disabled 처리
yoondgu Oct 17, 2023
2fc368c
fix: 이벤트를 통한 롤백 테스트 통합 테스트로 이동
yoondgu Oct 17, 2023
3592ff0
chore: #548과 충돌해결을 위한 merge
yoondgu Oct 17, 2023
5bfbcfc
test: 새로운 테스트에 테스트 컨테이너 적용
yoondgu Oct 17, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,10 @@ public double getLongitude() {
return location.getLongitude();
}

public String getDescription() {
return pinInfo.getDescription();
}

public String getRoadBaseAddress() {
Address address = location.getAddress();
return address.getRoadBaseAddress();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

import static org.apache.http.HttpHeaders.AUTHORIZATION;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doThrow;

import com.mapbefine.mapbefine.common.IntegrationTest;
import com.mapbefine.mapbefine.history.application.PinHistoryCommandService;
import com.mapbefine.mapbefine.location.LocationFixture;
import com.mapbefine.mapbefine.location.domain.Location;
import com.mapbefine.mapbefine.location.domain.LocationRepository;
Expand All @@ -14,9 +17,9 @@
import com.mapbefine.mapbefine.pin.domain.PinRepository;
import com.mapbefine.mapbefine.pin.dto.request.PinCreateRequest;
import com.mapbefine.mapbefine.pin.dto.request.PinUpdateRequest;
import com.mapbefine.mapbefine.pin.dto.response.PinDetailResponse;
import com.mapbefine.mapbefine.pin.dto.response.PinImageResponse;
import com.mapbefine.mapbefine.pin.dto.response.PinResponse;
import com.mapbefine.mapbefine.pin.event.PinUpdateEvent;
import com.mapbefine.mapbefine.topic.TopicFixture;
import com.mapbefine.mapbefine.topic.domain.Topic;
import com.mapbefine.mapbefine.topic.domain.TopicRepository;
Expand All @@ -26,8 +29,10 @@
import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;

Expand All @@ -42,6 +47,9 @@ class PinIntegrationTest extends IntegrationTest {
private PinCreateRequest createRequestNoDuplicateLocation;
private PinCreateRequest createRequestNoDuplicateLocation2;


@MockBean
private PinHistoryCommandService pinHistoryCommandService;
@Autowired
private MemberRepository memberRepository;

Expand Down Expand Up @@ -118,6 +126,16 @@ private ExtractableResponse<Response> createPin(PinCreateRequest request) {
.extract();
}

private ExtractableResponse<Response> updatePin(PinUpdateRequest request, long pinId) {
return RestAssured.given().log().all()
.header(AUTHORIZATION, authHeader)
.contentType(MediaType.APPLICATION_JSON_VALUE)
.body(request)
.when().put("/pins/" + pinId)
.then().log().all()
.extract();
}

@Test
@DisplayName("Image List 없이 Pin 을 정상적으로 생성한다.")
void addIfNonExistImageList_Success() {
Expand Down Expand Up @@ -153,14 +171,10 @@ void updatePin_Success() {
ExtractableResponse<Response> createResponse = createPin(createRequestNoDuplicateLocation);

// when
final PinUpdateRequest request = new PinUpdateRequest("핀 수정", "수정 설명");
final ExtractableResponse<Response> response = RestAssured.given().log().all()
.header(AUTHORIZATION, authHeader)
.contentType(MediaType.APPLICATION_JSON_VALUE)
.body(request)
.when().put(createResponse.header("Location"))
.then().log().all()
.extract();
PinUpdateRequest request = new PinUpdateRequest("핀 수정", "수정 설명");
String pinLocation = createResponse.header("Location");
long pinId = Long.parseLong(pinLocation.replace("/pins/", ""));
ExtractableResponse<Response> response = updatePin(request, pinId);

//then
assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value());
Expand Down Expand Up @@ -200,8 +214,6 @@ void findDetail_Success() {
// when
ExtractableResponse<Response> response = findById(pinId);

PinDetailResponse as = response.as(PinDetailResponse.class);

// then
assertThat(response.jsonPath().getString("name"))
.isEqualTo(createRequestNoDuplicateLocation.name());
Expand Down Expand Up @@ -301,5 +313,45 @@ void findAllPinsByMemberId_Success() {
assertThat(pinResponses).hasSize(1);
}

@Nested
class EventListenerTest {

@Test
@DisplayName("Pin 저장 시 변경 이력 저장에 예외가 발생하면, 변경 사항을 함께 롤백한다.")
void savePin_FailBySaveHistory_Rollback() {
//given
doThrow(new IllegalStateException()).when(pinHistoryCommandService).saveHistory(any(PinUpdateEvent.class));
Copy link
Collaborator

Choose a reason for hiding this comment

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

말씀대로 IntegrationTest 로 옮겨서 해결해주셨군요 굳굳


// when
ExtractableResponse<Response> response = createPin(createRequestNoDuplicateLocation);

//then
assertThat(response.statusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR.value());
assertThat(pinRepository.findAll()).isEmpty();
}

@Test
@DisplayName("Pin 수정 시 변경 이력 저장에 예외가 발생하면, 변경 사항을 함께 롤백한다.")
void updatePin_FailBySaveHistory_Rollback() {
//given
ExtractableResponse<Response> createResponse = createPin(createRequestNoDuplicateLocation);
String pinLocation = createResponse.header("Location");
long pinId = Long.parseLong(pinLocation.replace("/pins/", ""));
doThrow(new IllegalStateException()).when(pinHistoryCommandService).saveHistory(any(PinUpdateEvent.class));

// when
PinUpdateRequest request = new PinUpdateRequest("pin update", "description");
ExtractableResponse<Response> response = updatePin(request, pinId);

//then
assertThat(response.statusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR.value());
assertThat(pinRepository.findById(pinId)).isPresent()
.usingRecursiveComparison()
.withEqualsForFields(Object::equals, "name", "description")
.isNotEqualTo(request);
}

}

}

Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
Expand Down Expand Up @@ -40,7 +39,6 @@
import java.util.List;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
Expand Down Expand Up @@ -183,20 +181,6 @@ void save_Fail_DoNotSaveHistory() {
verify(pinHistoryCommandService, never()).saveHistory(any(PinUpdateEvent.class));
}

@Disabled
@Test
@DisplayName("핀 정보 이력 저장 시 예외가 발생하면, 추가된 핀 정보도 저장하지 않는다.")
void save_FailBySaveHistoryException() {
// given
doThrow(new IllegalStateException()).when(pinHistoryCommandService).saveHistory(any(PinUpdateEvent.class));

// when
// then
assertThatThrownBy(() -> pinCommandService.save(authMember, List.of(BASE_IMAGE_FILE), createRequest))
.isInstanceOf(IllegalStateException.class);
assertThat(pinRepository.findAll()).isEmpty();
}

@Test
@DisplayName("권한이 없는 토픽에 핀을 저장하면 예외를 발생시킨다.")
void save_FailByForbidden() {
Expand Down Expand Up @@ -252,26 +236,6 @@ void update_Fail_DoNotSaveHistory() {
verify(pinHistoryCommandService, never()).saveHistory(any(PinUpdateEvent.class));
}

@Test
@DisplayName("핀 정보 이력 저장 시 예외가 발생하면, 수정된 핀 정보도 저장하지 않는다.")
void update_FailBySaveHistoryException() {
// given
long pinId = pinCommandService.save(authMember, List.of(BASE_IMAGE_FILE), createRequest);

// when
doThrow(new IllegalStateException()).when(pinHistoryCommandService).saveHistory(any(PinUpdateEvent.class));
PinUpdateRequest request = new PinUpdateRequest("name", "update");

// then
assertThatThrownBy(() -> pinCommandService.update(authMember, pinId, request))
.isInstanceOf(IllegalStateException.class);
pinRepository.findById(pinId)
.ifPresentOrElse(
pin -> assertThat(pin.getUpdatedAt()).isEqualTo(pin.getCreatedAt()),
Assertions::fail
);
}

@Test
@DisplayName("권한이 없는 토픽에 핀을 수정하면 예외를 발생시킨다.")
void update_FailByForbidden() {
Expand Down
Loading