Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -23,7 +23,7 @@ public Long grantLoveToUserWithDistance(RunningRecord runningRecord) {
User user = userFinder.findUserById(runningRecord.getUserId())
.orElseThrow(IllegalStateException::new);
Long loveAmount = calculateLoveAmount(runningRecord.getTotalDistance());
LovePoint lovePoint = lovePointProcessor.updateLovePoint(user.getId(), loveAmount);
LovePoint lovePoint = lovePointProcessor.acquireLovePoint(user.getId(), loveAmount);
return lovePoint.getAmount();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,18 @@ public LovePointProcessor(LovePointRepository lovePointRepository) {
* 유저의 러브포인트를 업데이트한다. XLOCK을 걸어서 동시성 문제를 해결한다.
* */
@Transactional
public LovePoint updateLovePoint(Long userId, Long loveAmount) {
public LovePoint acquireLovePoint(Long userId, Long loveAmount) {
LovePoint lp = lovePointRepository.findByUserIdWithXLock(userId)
.orElseThrow(IllegalStateException::new);
lp.add(loveAmount);
return lovePointRepository.save(lp);
}

@Transactional
public LovePoint useLovePoint(Long userId, Long loveAmount) {
LovePoint lp = lovePointRepository.findByUserIdWithXLock(userId)
.orElseThrow(IllegalStateException::new);
lp.subtract(loveAmount);
return lovePointRepository.save(lp);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public class GiveLovePointToEggUsecaseImpl implements GiveLovePointToEggUsecase
@Transactional
public UseLovePointResponse execute(UseLovePointCommand command) {
IncubatingEgg incubatingEgg = incubatingEggProcessor.giveLovePoint(command);
lovePointProcessor.updateLovePoint(command.userId(), command.lovePoint());
lovePointProcessor.useLovePoint(command.userId(), command.lovePoint());
return new UseLovePointResponse(
incubatingEgg.getId(),
incubatingEgg.getCurrentLovePointAmount(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,9 @@
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.jdbc.Sql;

import java.util.Optional;

import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.*;
import static org.junit.jupiter.api.Assertions.assertEquals;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles("test")
Expand Down Expand Up @@ -111,4 +109,135 @@ void tearDown() {
.body("payload.required_love_point_amount", equalTo(100))
.body("payload.egg_hatchable", equalTo(false));
}

@Test
@Sql(scripts = "/sql/incubating_egg_test_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
void 알에_애정을_부여하면_사용자의_보유_애정이_감소한다() throws JsonProcessingException {
// given
String userUuid = "test-user-uuid-1";
String token = "Bearer " + jwtTokenFactory.generateAccessToken(userUuid);

// 사용자의 초기 애정 포인트 조회
Integer initialLovePoint = given()
.header("Authorization", token)
.contentType(ContentType.JSON)
.when()
.get("/api/v1/main")
.then()
.statusCode(200)
.extract()
.path("payload.love_point");

// when
// 20포인트의 애정을 부여
Long useLovePointAmount = 20L;
UseLovePointRequest request = new UseLovePointRequest(1L, useLovePointAmount);

// 알에 애정 부여 요청
given()
.header("Authorization", token)
.contentType(ContentType.JSON)
.body(objectMapper.writeValueAsString(request))
.when()
.patch("/api/v1/users/eggs")
.then()
.log().all()
.statusCode(200)
.body("payload.current_love_point_amount", equalTo(70));

// then
// 사용자의 애정 포인트가 감소했는지 확인
given()
.header("Authorization", token)
.contentType(ContentType.JSON)
.when()
.get("/api/v1/main")
.then()
.log().all()
.statusCode(200)
.body("payload.love_point", equalTo(initialLovePoint - useLovePointAmount.intValue()));
}


@Test
@Sql(scripts = "/sql/incubating_egg_test_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
void 보유한_애정보다_더_많은_애정부여_요청_시_예외() throws JsonProcessingException {
// given
String userUuid = "test-user-uuid-1";
String token = "Bearer " + jwtTokenFactory.generateAccessToken(userUuid);

// 사용자의 초기 애정 포인트 조회
given()
.header("Authorization", token)
.contentType(ContentType.JSON)
.when()
.get("/api/v1/main")
.then()
.statusCode(200)
.extract()
.path("payload.love_point");

// when
// 20포인트의 애정을 부여
Long useLovePointAmount = 25L;
UseLovePointRequest request = new UseLovePointRequest(1L, useLovePointAmount);

// 알에 애정 부여 요청
given()
.header("Authorization", token)
.contentType(ContentType.JSON)
.body(objectMapper.writeValueAsString(request))
.when()
.patch("/api/v1/users/eggs")
.then()
.log().all()
.statusCode(400);
}

@Test
@Sql(scripts = "/sql/incubating_egg_test_data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
void 애정부여_예외_시_애정보유량_유지() throws JsonProcessingException {
// given
String userUuid = "test-user-uuid-1";
String token = "Bearer " + jwtTokenFactory.generateAccessToken(userUuid);

// 사용자의 초기 애정 포인트 조회
Integer initialLovePoint = given()
.header("Authorization", token)
.contentType(ContentType.JSON)
.when()
.get("/api/v1/main")
.then()
.statusCode(200)
.extract()
.path("payload.love_point");

// when
// 20포인트의 애정을 부여
Long useLovePointAmount = 25L;
UseLovePointRequest request = new UseLovePointRequest(1L, useLovePointAmount);

// 알에 애정 부여 요청
given()
.header("Authorization", token)
.contentType(ContentType.JSON)
.body(objectMapper.writeValueAsString(request))
.when()
.patch("/api/v1/users/eggs")
.then()
.log().all()
.statusCode(400);

// then
// 사용자의 애정 포인트가 감소했는지 확인
given()
.header("Authorization", token)
.contentType(ContentType.JSON)
.when()
.get("/api/v1/main")
.then()
.log().all()
.statusCode(200)
.body("payload.love_point", equalTo(initialLovePoint));
}
}
2 changes: 1 addition & 1 deletion src/test/resources/sql/incubating_egg_test_data.sql
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ INSERT INTO users (id, public_id, nickname, img_url, total_distance_in_meters, t
VALUES (1, 'test-user-uuid-1', 'Daniel', 'https://example.com/images/user1.png', 3000, 3600, NOW(), NOW());

INSERT INTO user_love_point (id, user_id, amount, created_at, updated_at)
VALUES (1, 1, 1000, NOW(), NOW());
VALUES (1, 1, 20, NOW(), NOW());

-- 보유 아이템
INSERT INTO user_item (id, user_id, item_id, quantity, created_at, updated_at)
Expand Down