diff --git a/src/main/java/camp/woowak/lab/customer/domain/Customer.java b/src/main/java/camp/woowak/lab/customer/domain/Customer.java index be53fb4f..4bf75642 100644 --- a/src/main/java/camp/woowak/lab/customer/domain/Customer.java +++ b/src/main/java/camp/woowak/lab/customer/domain/Customer.java @@ -1,5 +1,7 @@ package camp.woowak.lab.customer.domain; +import java.util.UUID; + import camp.woowak.lab.customer.exception.InvalidCreationException; import camp.woowak.lab.payaccount.domain.PayAccount; import camp.woowak.lab.web.authentication.PasswordEncoder; @@ -10,14 +12,16 @@ import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; import lombok.Getter; @Entity @Getter +@Table(name = "Customers") public class Customer { @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; + @GeneratedValue(strategy = GenerationType.UUID) + private UUID id; @Column(nullable = false, length = 50) private String name; @Column(unique = true, nullable = false, length = 100) diff --git a/src/main/java/camp/woowak/lab/customer/service/SignUpCustomerService.java b/src/main/java/camp/woowak/lab/customer/service/SignUpCustomerService.java index d43aad29..e6f8c634 100644 --- a/src/main/java/camp/woowak/lab/customer/service/SignUpCustomerService.java +++ b/src/main/java/camp/woowak/lab/customer/service/SignUpCustomerService.java @@ -12,7 +12,9 @@ import camp.woowak.lab.payaccount.repository.PayAccountRepository; import camp.woowak.lab.web.authentication.PasswordEncoder; import jakarta.transaction.Transactional; +import lombok.extern.slf4j.Slf4j; +@Slf4j @Service public class SignUpCustomerService { private final CustomerRepository customerRepository; @@ -32,7 +34,7 @@ public SignUpCustomerService(CustomerRepository customerRepository, PayAccountRe * @throws DuplicateEmailException 이메일이 중복되는 경우 */ @Transactional - public Long signUp(SignUpCustomerCommand cmd) { + public String signUp(SignUpCustomerCommand cmd) { PayAccount payAccount = new PayAccount(); payAccountRepository.save(payAccount); @@ -40,10 +42,10 @@ public Long signUp(SignUpCustomerCommand cmd) { passwordEncoder); try { - customerRepository.save(newCustomer); + return customerRepository.saveAndFlush(newCustomer).getId().toString(); } catch (DataIntegrityViolationException e) { + log.error("데이터 무결성 위반"); throw new DuplicateEmailException(); } - return newCustomer.getId(); } } diff --git a/src/main/java/camp/woowak/lab/payaccount/repository/PayAccountRepository.java b/src/main/java/camp/woowak/lab/payaccount/repository/PayAccountRepository.java index 22120a4c..597fef70 100644 --- a/src/main/java/camp/woowak/lab/payaccount/repository/PayAccountRepository.java +++ b/src/main/java/camp/woowak/lab/payaccount/repository/PayAccountRepository.java @@ -1,6 +1,7 @@ package camp.woowak.lab.payaccount.repository; import java.util.Optional; +import java.util.UUID; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Lock; @@ -13,5 +14,5 @@ public interface PayAccountRepository extends JpaRepository { @Lock(LockModeType.PESSIMISTIC_WRITE) @Query("SELECT pa FROM PayAccount pa LEFT JOIN Customer c on c.payAccount = pa where c.id = :customerId") - Optional findByCustomerIdForUpdate(@Param("customerId") Long customerId); + Optional findByCustomerIdForUpdate(@Param("customerId") UUID customerId); } diff --git a/src/main/java/camp/woowak/lab/payaccount/service/command/PayAccountChargeCommand.java b/src/main/java/camp/woowak/lab/payaccount/service/command/PayAccountChargeCommand.java index a1c46ff8..3be63f5c 100644 --- a/src/main/java/camp/woowak/lab/payaccount/service/command/PayAccountChargeCommand.java +++ b/src/main/java/camp/woowak/lab/payaccount/service/command/PayAccountChargeCommand.java @@ -1,6 +1,8 @@ package camp.woowak.lab.payaccount.service.command; +import java.util.UUID; + public record PayAccountChargeCommand( - Long customerId, + UUID customerId, long amount) { } \ No newline at end of file diff --git a/src/main/java/camp/woowak/lab/web/api/customer/CustomerApiController.java b/src/main/java/camp/woowak/lab/web/api/customer/CustomerApiController.java index 6dbb9f9b..4097e2f5 100644 --- a/src/main/java/camp/woowak/lab/web/api/customer/CustomerApiController.java +++ b/src/main/java/camp/woowak/lab/web/api/customer/CustomerApiController.java @@ -28,7 +28,7 @@ public SignUpCustomerResponse signUp(@Valid @RequestBody SignUpCustomerRequest r SignUpCustomerCommand command = new SignUpCustomerCommand(request.name(), request.email(), request.password(), request.phone()); - Long registeredId = signUpCustomerService.signUp(command); + String registeredId = signUpCustomerService.signUp(command); response.setHeader("Location", "/customers/" + registeredId); diff --git a/src/main/java/camp/woowak/lab/web/authentication/LoginCustomer.java b/src/main/java/camp/woowak/lab/web/authentication/LoginCustomer.java index 0a55c31d..b0d57ee9 100644 --- a/src/main/java/camp/woowak/lab/web/authentication/LoginCustomer.java +++ b/src/main/java/camp/woowak/lab/web/authentication/LoginCustomer.java @@ -1,14 +1,16 @@ package camp.woowak.lab.web.authentication; +import java.util.UUID; + public class LoginCustomer implements LoginMember { - private final Long id; + private final UUID id; - public LoginCustomer(Long id) { + public LoginCustomer(UUID id) { this.id = id; } @Override - public Long getId() { + public UUID getId() { return id; } } diff --git a/src/main/java/camp/woowak/lab/web/dto/response/customer/SignUpCustomerResponse.java b/src/main/java/camp/woowak/lab/web/dto/response/customer/SignUpCustomerResponse.java index 87b9a605..63c4c238 100644 --- a/src/main/java/camp/woowak/lab/web/dto/response/customer/SignUpCustomerResponse.java +++ b/src/main/java/camp/woowak/lab/web/dto/response/customer/SignUpCustomerResponse.java @@ -1,4 +1,4 @@ package camp.woowak.lab.web.dto.response.customer; -public record SignUpCustomerResponse(Long id) { +public record SignUpCustomerResponse(String id) { } diff --git a/src/test/java/camp/woowak/lab/customer/service/SignUpCustomerServiceIntegrationTest.java b/src/test/java/camp/woowak/lab/customer/service/SignUpCustomerServiceIntegrationTest.java index afb237b4..3deaf454 100644 --- a/src/test/java/camp/woowak/lab/customer/service/SignUpCustomerServiceIntegrationTest.java +++ b/src/test/java/camp/woowak/lab/customer/service/SignUpCustomerServiceIntegrationTest.java @@ -6,9 +6,9 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.dao.DataIntegrityViolationException; import camp.woowak.lab.customer.exception.DuplicateEmailException; -import camp.woowak.lab.customer.exception.InvalidCreationException; import camp.woowak.lab.customer.repository.CustomerRepository; import camp.woowak.lab.customer.service.command.SignUpCustomerCommand; import camp.woowak.lab.payaccount.repository.PayAccountRepository; @@ -27,7 +27,7 @@ class SignUpCustomerServiceIntegrationTest { @Test @DisplayName("이메일 중복 시 롤백 테스트") - void testRollbackOnDuplicateEmail() throws InvalidCreationException, DuplicateEmailException { + void testRollbackOnDuplicateEmail() { // given SignUpCustomerCommand command1 = new SignUpCustomerCommand("name1", "email@example.com", "password", "010-1234-5678"); @@ -43,10 +43,11 @@ void testRollbackOnDuplicateEmail() throws InvalidCreationException, DuplicateEm // then try { service.signUp(command2); - fail("중복 이메일 예외가 발생해야 합니다."); } catch (DuplicateEmailException e) { assertEquals(1, customerRepository.count()); assertEquals(1, payAccountRepository.count()); + } catch (DataIntegrityViolationException e) { + fail("DataIntegrityViolationException이 발생했습니다."); } } -} \ No newline at end of file +} diff --git a/src/test/java/camp/woowak/lab/customer/service/SignUpCustomerServiceTest.java b/src/test/java/camp/woowak/lab/customer/service/SignUpCustomerServiceTest.java index f3bbb0d9..2bf04d9a 100644 --- a/src/test/java/camp/woowak/lab/customer/service/SignUpCustomerServiceTest.java +++ b/src/test/java/camp/woowak/lab/customer/service/SignUpCustomerServiceTest.java @@ -2,6 +2,8 @@ import static org.mockito.BDDMockito.*; +import java.util.UUID; + import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -14,13 +16,11 @@ import camp.woowak.lab.customer.domain.Customer; import camp.woowak.lab.customer.exception.DuplicateEmailException; -import camp.woowak.lab.customer.exception.InvalidCreationException; import camp.woowak.lab.customer.repository.CustomerRepository; import camp.woowak.lab.customer.service.command.SignUpCustomerCommand; import camp.woowak.lab.fixture.CustomerFixture; import camp.woowak.lab.payaccount.domain.PayAccount; import camp.woowak.lab.payaccount.repository.PayAccountRepository; -import camp.woowak.lab.web.authentication.NoOpPasswordEncoder; import camp.woowak.lab.web.authentication.PasswordEncoder; @ExtendWith(MockitoExtension.class) @@ -40,13 +40,14 @@ class SignUpCustomerServiceTest implements CustomerFixture { @Test @DisplayName("구매자 회원가입 테스트") - void testSignUp() throws InvalidCreationException, DuplicateEmailException { + void testSignUp() { // given given(passwordEncoder.encode(Mockito.anyString())).willReturn("password"); PayAccount payAccount = createPayAccount(); - Customer customer = createCustomer(payAccount, new NoOpPasswordEncoder()); + Customer customerMock = Mockito.mock(Customer.class); given(payAccountRepository.save(Mockito.any(PayAccount.class))).willReturn(payAccount); - given(customerRepository.save(Mockito.any(Customer.class))).willReturn(customer); + given(customerRepository.saveAndFlush(Mockito.any(Customer.class))).willReturn(customerMock); + when(customerMock.getId()).thenReturn(UUID.randomUUID()); // when SignUpCustomerCommand command = @@ -55,7 +56,7 @@ void testSignUp() throws InvalidCreationException, DuplicateEmailException { // then then(payAccountRepository).should().save(Mockito.any(PayAccount.class)); - then(customerRepository).should().save(Mockito.any(Customer.class)); + then(customerRepository).should().saveAndFlush(Mockito.any(Customer.class)); } @Test @@ -64,7 +65,8 @@ void testSignUpWithExistingEmail() { // given given(passwordEncoder.encode(Mockito.anyString())).willReturn("password"); given(payAccountRepository.save(Mockito.any(PayAccount.class))).willReturn(createPayAccount()); - when(customerRepository.save(Mockito.any(Customer.class))).thenThrow(DataIntegrityViolationException.class); + when(customerRepository.saveAndFlush(Mockito.any(Customer.class))).thenThrow( + DataIntegrityViolationException.class); // when SignUpCustomerCommand command = @@ -73,6 +75,6 @@ void testSignUpWithExistingEmail() { // then Assertions.assertThrows(DuplicateEmailException.class, () -> service.signUp(command)); then(payAccountRepository).should().save(Mockito.any(PayAccount.class)); - then(customerRepository).should().save(Mockito.any(Customer.class)); + then(customerRepository).should().saveAndFlush(Mockito.any(Customer.class)); } -} \ No newline at end of file +} diff --git a/src/test/java/camp/woowak/lab/payaccount/service/PayAccountChargeServiceTest.java b/src/test/java/camp/woowak/lab/payaccount/service/PayAccountChargeServiceTest.java index 2131d9ea..2239e193 100644 --- a/src/test/java/camp/woowak/lab/payaccount/service/PayAccountChargeServiceTest.java +++ b/src/test/java/camp/woowak/lab/payaccount/service/PayAccountChargeServiceTest.java @@ -3,6 +3,7 @@ import static org.assertj.core.api.Assertions.*; import java.util.Optional; +import java.util.UUID; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -71,7 +72,7 @@ void withdrawAccount() { @DisplayName("없는 AccountId를 호출하면 NotFoundAccountException을 던진다. 잔고는 유지된다.") void withdrawAccountNotFound() { //given - Long unknownAccountId = Long.MAX_VALUE; + UUID unknownAccountId = UUID.randomUUID(); long amount = 100L; PayAccountChargeCommand command = new PayAccountChargeCommand(unknownAccountId, amount); diff --git a/src/test/java/camp/woowak/lab/web/api/PayAccountApiControllerTest.java b/src/test/java/camp/woowak/lab/web/api/PayAccountApiControllerTest.java index 16a09cfb..e8735cd3 100644 --- a/src/test/java/camp/woowak/lab/web/api/PayAccountApiControllerTest.java +++ b/src/test/java/camp/woowak/lab/web/api/PayAccountApiControllerTest.java @@ -6,6 +6,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; import java.util.Optional; +import java.util.UUID; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -102,9 +103,9 @@ void successTest() throws Exception { //when & then mvc.perform(post(BASE_URL) - .contentType(MediaType.APPLICATION_JSON_VALUE) - .content(objectMapper.writeValueAsBytes(command)) - .session(session)) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .content(objectMapper.writeValueAsBytes(command)) + .session(session)) .andExpect(status().isOk()) .andExpect(jsonPath("$.status").value(HttpStatus.OK.value())) .andExpect(jsonPath("$.data.balance").value(amount + originBalance)); @@ -122,9 +123,9 @@ void dailyLimitExceededTest() throws Exception { //when & then ResultActions actions = mvc.perform(post(BASE_URL) - .contentType(MediaType.APPLICATION_JSON_VALUE) - .content(objectMapper.writeValueAsBytes(command)) - .session(session)) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .content(objectMapper.writeValueAsBytes(command)) + .session(session)) .andDo(print()) .andExpect(status().isBadRequest()); @@ -136,16 +137,16 @@ void dailyLimitExceededTest() throws Exception { void notExistsAccountIdTest() throws Exception { //given long amount = 1000L; - Long notExistsId = Long.MAX_VALUE; + UUID notExistsId = UUID.randomUUID(); MockHttpSession notExistsSession = new MockHttpSession(); notExistsSession.setAttribute(SessionConst.SESSION_CUSTOMER_KEY, new LoginCustomer(notExistsId)); PayAccountChargeRequest command = new PayAccountChargeRequest(amount); //when & then ResultActions actions = mvc.perform(post(BASE_URL) - .contentType(MediaType.APPLICATION_JSON_VALUE) - .content(objectMapper.writeValueAsBytes(command)) - .session(notExistsSession)) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .content(objectMapper.writeValueAsBytes(command)) + .session(notExistsSession)) .andExpect(status().isNotFound()); validateErrorResponseWithErrorCode(actions, PayAccountErrorCode.ACCOUNT_NOT_FOUND); @@ -159,9 +160,9 @@ void nullAmountTest() throws Exception { //when & then ResultActions actions = mvc.perform(post(BASE_URL) - .contentType(MediaType.APPLICATION_JSON_VALUE) - .content(objectMapper.writeValueAsBytes(command)) - .session(session)) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .content(objectMapper.writeValueAsBytes(command)) + .session(session)) .andExpect(status().isBadRequest()); verificationPersistedBalance(payAccount.getId(), originBalance); @@ -176,9 +177,9 @@ void negativeAmountTest() throws Exception { //when & then ResultActions actions = mvc.perform(post(BASE_URL) - .contentType(MediaType.APPLICATION_JSON_VALUE) - .content(objectMapper.writeValueAsBytes(command)) - .session(session)) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .content(objectMapper.writeValueAsBytes(command)) + .session(session)) .andExpect(status().isBadRequest()); validateErrorResponseWithErrorCode(actions, PayAccountErrorCode.INVALID_TRANSACTION_AMOUNT); diff --git a/src/test/java/camp/woowak/lab/web/api/customer/CustomerApiControllerTest.java b/src/test/java/camp/woowak/lab/web/api/customer/CustomerApiControllerTest.java index 4d55fbe2..d303ac00 100644 --- a/src/test/java/camp/woowak/lab/web/api/customer/CustomerApiControllerTest.java +++ b/src/test/java/camp/woowak/lab/web/api/customer/CustomerApiControllerTest.java @@ -5,6 +5,8 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; +import java.util.UUID; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -38,9 +40,10 @@ class CustomerApiControllerTest { @DisplayName("구매자 회원가입 테스트 - 성공") void testSignUpCustomer() throws Exception { // given + String customerId = UUID.randomUUID().toString(); SignUpCustomerRequest request = new SignUpCustomerRequest("name", "email@test.com", "password123", "010-1234-5678"); - given(signUpCustomerService.signUp(any())).willReturn(1L); + given(signUpCustomerService.signUp(any())).willReturn(customerId); // when & then mockMvc.perform(post("/customers")