diff --git a/logbat/src/main/java/info/logbat/common/util/UUIDUtil.java b/logbat/src/main/java/info/logbat/common/util/UUIDUtil.java new file mode 100644 index 0000000..966486a --- /dev/null +++ b/logbat/src/main/java/info/logbat/common/util/UUIDUtil.java @@ -0,0 +1,28 @@ +package info.logbat.common.util; + +import java.nio.ByteBuffer; +import java.util.UUID; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public final class UUIDUtil { + + private static final int UUID_BYTE_LENGTH = 16; + + public static byte[] uuidStringToBytes(String uuidStr) { + UUID uuid = UUID.fromString(uuidStr); + ByteBuffer byteBuffer = ByteBuffer.wrap(new byte[UUID_BYTE_LENGTH]); + byteBuffer.putLong(uuid.getMostSignificantBits()); + byteBuffer.putLong(uuid.getLeastSignificantBits()); + return byteBuffer.array(); + } + + public static String bytesToUuidString(byte[] bytes) { + ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); + long high = byteBuffer.getLong(); + long low = byteBuffer.getLong(); + UUID uuid = new UUID(high, low); + return uuid.toString(); + } +} diff --git a/logbat/src/main/java/info/logbat/domain/log/application/LogService.java b/logbat/src/main/java/info/logbat/domain/log/application/LogService.java index b4fdfbb..002fcaa 100644 --- a/logbat/src/main/java/info/logbat/domain/log/application/LogService.java +++ b/logbat/src/main/java/info/logbat/domain/log/application/LogService.java @@ -14,13 +14,13 @@ public class LogService { private final LogRepository logRepository; public long saveLog(CreateLogServiceRequest request) { - Long appId = request.applicationId(); - String logLevel = request.logLevel(); - String logData = request.logData(); + String appKey = request.appKey(); + String level = request.level(); + String data = request.data(); LocalDateTime timestamp = request.timestamp(); // TODO Log 저장 전 Application ID 체크 로직 추가 필요 - Log log = Log.of(appId, logLevel, logData, timestamp); + Log log = Log.of(appKey, level, data, timestamp); return logRepository.save(log); } diff --git a/logbat/src/main/java/info/logbat/domain/log/application/payload/request/CreateLogServiceRequest.java b/logbat/src/main/java/info/logbat/domain/log/application/payload/request/CreateLogServiceRequest.java index 19a7f15..8402342 100644 --- a/logbat/src/main/java/info/logbat/domain/log/application/payload/request/CreateLogServiceRequest.java +++ b/logbat/src/main/java/info/logbat/domain/log/application/payload/request/CreateLogServiceRequest.java @@ -4,17 +4,17 @@ import java.time.LocalDateTime; public record CreateLogServiceRequest( - Long applicationId, - String logLevel, - String logData, + String appKey, + String level, + String data, LocalDateTime timestamp ) { - public static CreateLogServiceRequest of(Long applicationId, CreateLogRequest request) { + public static CreateLogServiceRequest of(String appKey, CreateLogRequest request) { return new CreateLogServiceRequest( - applicationId, - request.logLevel(), - request.logData(), + appKey, + request.level(), + request.data(), request.timestamp() ); } diff --git a/logbat/src/main/java/info/logbat/domain/log/domain/Log.java b/logbat/src/main/java/info/logbat/domain/log/domain/Log.java index 531b0ea..e9d35d2 100644 --- a/logbat/src/main/java/info/logbat/domain/log/domain/Log.java +++ b/logbat/src/main/java/info/logbat/domain/log/domain/Log.java @@ -9,33 +9,33 @@ public class Log { private final Long logId; - private final Long applicationId; + private final String appKey; private final Level level; - private final LogData logData; + private final LogData data; private final LocalDateTime timestamp; - public static Log of(Long applicationId, String level, String logData, LocalDateTime timestamp) { - return new Log(applicationId, level, logData, timestamp); + public static Log of(String appKey, String level, String logData, LocalDateTime timestamp) { + return new Log(appKey, level, logData, timestamp); } - public Log(Long applicationId, String level, String logData, LocalDateTime timestamp) { - this(null, applicationId, level, logData, timestamp); + public Log(String appKey, String level, String data, LocalDateTime timestamp) { + this(null, appKey, level, data, timestamp); } - public Log(Long logId, Long applicationId, String level, String logData, + public Log(Long logId, String appKey, String level, String data, LocalDateTime timestamp) { this.logId = logId; - validateApplicationId(applicationId); - this.applicationId = applicationId; + validateAppKey(appKey); + this.appKey = appKey; this.level = Level.from(level); - this.logData = LogData.from(logData); + this.data = LogData.from(data); validateTimestamp(timestamp); this.timestamp = timestamp; } - private void validateApplicationId(Long applicationId) { - if (applicationId == null) { - throw new IllegalArgumentException("applicationId는 null이 될 수 없습니다."); + private void validateAppKey(String appKey) { + if (appKey == null || appKey.isBlank()) { + throw new IllegalArgumentException("appKey는 null이거나 빈 문자열이 될 수 없습니다."); } } diff --git a/logbat/src/main/java/info/logbat/domain/log/presentation/LogController.java b/logbat/src/main/java/info/logbat/domain/log/presentation/LogController.java index f7535ba..7ec8659 100644 --- a/logbat/src/main/java/info/logbat/domain/log/presentation/LogController.java +++ b/logbat/src/main/java/info/logbat/domain/log/presentation/LogController.java @@ -4,14 +4,14 @@ import info.logbat.domain.log.application.payload.request.CreateLogServiceRequest; import info.logbat.domain.log.presentation.payload.request.CreateLogRequest; import jakarta.validation.Valid; -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Positive; +import jakarta.validation.constraints.NotBlank; import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; +import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; @RestController @@ -22,18 +22,15 @@ public class LogController { private final LogService logService; @PostMapping - public ResponseEntity saveLog( - @RequestHeader("app-id") - @NotNull(message = "Application ID가 비어있습니다.") - @Positive(message = "Application ID는 양수여야 합니다.") Long applicationId, + @ResponseStatus(HttpStatus.CREATED) + public void saveLog( + @RequestHeader("appKey") + @NotBlank(message = "appKey가 비어있습니다.") String appKey, @Valid @RequestBody CreateLogRequest request ) { - logService.saveLog(CreateLogServiceRequest.of(applicationId, request)); - - return ResponseEntity.ok() - .build(); + logService.saveLog(CreateLogServiceRequest.of(appKey, request)); } } diff --git a/logbat/src/main/java/info/logbat/domain/log/presentation/payload/request/CreateLogRequest.java b/logbat/src/main/java/info/logbat/domain/log/presentation/payload/request/CreateLogRequest.java index ef8146b..c8b631e 100644 --- a/logbat/src/main/java/info/logbat/domain/log/presentation/payload/request/CreateLogRequest.java +++ b/logbat/src/main/java/info/logbat/domain/log/presentation/payload/request/CreateLogRequest.java @@ -6,10 +6,10 @@ public record CreateLogRequest( @NotBlank(message = "로그 레벨이 비어있습니다.") - String logLevel, + String level, @NotBlank(message = "로그 데이터가 비어있습니다.") - String logData, + String data, @NotNull(message = "타임스탬프가 비어있습니다.") LocalDateTime timestamp diff --git a/logbat/src/main/java/info/logbat/domain/log/repository/LogRepository.java b/logbat/src/main/java/info/logbat/domain/log/repository/LogRepository.java index 73f38c6..dde1b70 100644 --- a/logbat/src/main/java/info/logbat/domain/log/repository/LogRepository.java +++ b/logbat/src/main/java/info/logbat/domain/log/repository/LogRepository.java @@ -1,5 +1,6 @@ package info.logbat.domain.log.repository; +import info.logbat.common.util.UUIDUtil; import info.logbat.domain.log.domain.Log; import java.sql.PreparedStatement; import java.sql.Statement; @@ -20,15 +21,15 @@ public class LogRepository { private final JdbcTemplate jdbcTemplate; public long save(Log log) { - String sql = "INSERT INTO logs (application_id, level, log_data, timestamp) VALUES (?, ?, ?, ?)"; + String sql = "INSERT INTO logs (app_key, level, data, timestamp) VALUES (?, ?, ?, ?)"; KeyHolder keyHolder = new GeneratedKeyHolder(); jdbcTemplate.update(connection -> { PreparedStatement ps = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS); - ps.setLong(1, log.getApplicationId()); + ps.setBytes(1, UUIDUtil.uuidStringToBytes(log.getAppKey())); ps.setString(2, log.getLevel().name()); - ps.setString(3, log.getLogData().getValue()); + ps.setString(3, log.getData().getValue()); ps.setTimestamp(4, Timestamp.valueOf(log.getTimestamp())); return ps; }, keyHolder); @@ -55,9 +56,9 @@ public Optional findById(Long logId) { private static final RowMapper LOG_ROW_MAPPER = (rs, rowNum) -> new Log( rs.getLong("log_id"), - rs.getLong("application_id"), + UUIDUtil.bytesToUuidString(rs.getBytes("app_key")), rs.getString("level"), - rs.getString("log_data"), + rs.getString("data"), rs.getTimestamp("timestamp").toLocalDateTime() ); } diff --git a/logbat/src/test/java/info/logbat/common/util/UUIDUtilTest.java b/logbat/src/test/java/info/logbat/common/util/UUIDUtilTest.java new file mode 100644 index 0000000..f223877 --- /dev/null +++ b/logbat/src/test/java/info/logbat/common/util/UUIDUtilTest.java @@ -0,0 +1,51 @@ +package info.logbat.common.util; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; + +import java.util.stream.Stream; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +@DisplayName("UUIDUtil에서 ") +public class UUIDUtilTest { + + @ParameterizedTest + @DisplayName("UUID 문자열은 byte 배열로 변환할 수 있다.") + @MethodSource("validUUIDProvider") + void uuidToBytes_ShouldConvertUUIDStringToByteArray(String uuidStr, byte[] expectedBytes) { + // when + byte[] bytes = UUIDUtil.uuidStringToBytes(uuidStr); + + assertAll( + () -> assertThat(bytes).isNotNull(), + () -> assertThat(bytes.length).isEqualTo(16), + () -> assertThat(bytes).isEqualTo(expectedBytes) + ); + } + + @ParameterizedTest + @DisplayName("bytesToUUIDString은 byte 배열을 UUID 문자열로 정확하게 변환해야 한다.") + @MethodSource("validUUIDProvider") + void bytesToUUIDString_ShouldConvertByteArrayToUUIDString(String expectedUUIDStr, byte[] bytes) { + // when + String resultUUIDStr = UUIDUtil.bytesToUuidString(bytes); + + // then + assertThat(resultUUIDStr).isEqualTo(expectedUUIDStr); + } + + + private static Stream validUUIDProvider() { + return Stream.of( + Arguments.of("550e8400-e29b-41d4-a716-446655440000", + new byte[]{85, 14, -124, 0, -30, -101, 65, -44, -89, 22, 68, 102, 85, 68, 0, 0}), + Arguments.of("123e4567-e89b-12d3-a456-426614174000", + new byte[]{18, 62, 69, 103, -24, -101, 18, -45, -92, 86, 66, 102, 20, 23, 64, 0}), + Arguments.of("00000000-0000-0000-0000-000000000000", + new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}) + ); + } +} \ No newline at end of file diff --git a/logbat/src/test/java/info/logbat/domain/log/application/LogServiceTest.java b/logbat/src/test/java/info/logbat/domain/log/application/LogServiceTest.java index fdd6ab8..dc7a0fd 100644 --- a/logbat/src/test/java/info/logbat/domain/log/application/LogServiceTest.java +++ b/logbat/src/test/java/info/logbat/domain/log/application/LogServiceTest.java @@ -8,6 +8,7 @@ import info.logbat.domain.log.repository.LogRepository; import java.time.LocalDateTime; import java.util.Optional; +import java.util.UUID; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -27,16 +28,17 @@ class LogServiceTest { @Autowired private LogRepository logRepository; + private static final String 앱_키_문자열 = UUID.randomUUID().toString(); + @DisplayName("Log를 저장할 수 있다.") @Test void saveLog() { // given - Long 어플리케이션_ID = 1L; String 로그_레벨 = "INFO"; String 로그_데이터 = "테스트_로그_데이터"; LocalDateTime 타임스탬프 = LocalDateTime.of(2021, 1, 1, 0, 0, 0); - CreateLogServiceRequest 요청_DTO = new CreateLogServiceRequest(어플리케이션_ID, 로그_레벨, 로그_데이터, 타임스탬프); + CreateLogServiceRequest 요청_DTO = new CreateLogServiceRequest(앱_키_문자열, 로그_레벨, 로그_데이터, 타임스탬프); // when long 저장된_ID = logService.saveLog(요청_DTO); @@ -46,8 +48,8 @@ void saveLog() { assertThat(찾은_로그).isPresent() .get() - .extracting("logId", "applicationId", "level", "logData.value", "timestamp") - .contains(저장된_ID, 1L, Level.INFO, "테스트_로그_데이터", 타임스탬프); + .extracting("logId", "appKey", "level", "data.value", "timestamp") + .contains(저장된_ID, 앱_키_문자열, Level.INFO, "테스트_로그_데이터", 타임스탬프); } } \ No newline at end of file diff --git a/logbat/src/test/java/info/logbat/domain/log/presentation/LogControllerTest.java b/logbat/src/test/java/info/logbat/domain/log/presentation/LogControllerTest.java index 833b1ff..c0629f7 100644 --- a/logbat/src/test/java/info/logbat/domain/log/presentation/LogControllerTest.java +++ b/logbat/src/test/java/info/logbat/domain/log/presentation/LogControllerTest.java @@ -8,6 +8,7 @@ import info.logbat.domain.common.ControllerTestSupport; import info.logbat.domain.log.presentation.payload.request.CreateLogRequest; import java.time.LocalDateTime; +import java.util.UUID; import java.util.stream.Stream; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -19,11 +20,12 @@ class LogControllerTest extends ControllerTestSupport { + private static final String 앱_키_문자열 = UUID.randomUUID().toString(); + @DisplayName("[POST] 로그를 정상적으로 생성한다.") @Test void createLog() throws Exception { // given - Long 어플리케이션_ID = 1L; String 로그_레벨 = "INFO"; String 로그_데이터 = "테스트_로그_데이터"; LocalDateTime 타임스탬프 = LocalDateTime.of(2021, 1, 1, 0, 0, 0); @@ -36,11 +38,11 @@ void createLog() throws Exception { // when ResultActions perform = mockMvc.perform(post("/logs") .contentType(MediaType.APPLICATION_JSON) - .header("app-id", 어플리케이션_ID) + .header("appKey", 앱_키_문자열) .content(objectMapper.writeValueAsString(요청_DTO))); // then - perform.andExpect(status().isOk()); + perform.andExpect(status().isCreated()); } @DisplayName("[POST] 어플리케이션_ID가 없으면 400 에러를 반환한다.") @@ -68,7 +70,7 @@ void createLogWithoutAppId() throws Exception { @DisplayName("[POST] 잘못된 입력으로 로그 생성 시 400 에러를 반환한다.") @ParameterizedTest(name = "{index}: {0}") @MethodSource("invalidLogCreationInputs") - void createLogWithInvalidInput(String testCase, Long appId, String level, String data, + void createLogWithInvalidInput(String testCase, String appKey, String level, String data, LocalDateTime timestamp) throws Exception { // given CreateLogRequest 요청_DTO = new CreateLogRequest(level, data, timestamp); @@ -77,7 +79,7 @@ void createLogWithInvalidInput(String testCase, Long appId, String level, String // when ResultActions perform = mockMvc.perform(post("/logs") .contentType(MediaType.APPLICATION_JSON) - .header("app-id", appId) + .header("appKey", 앱_키_문자열) .content(objectMapper.writeValueAsString(요청_DTO))); // then @@ -86,17 +88,15 @@ void createLogWithInvalidInput(String testCase, Long appId, String level, String private static Stream invalidLogCreationInputs() { return Stream.of( - Arguments.of("어플리케이션_ID가 음수인 경우", -1L, "INFO", "테스트_로그_데이터", - LocalDateTime.of(2021, 1, 1, 0, 0, 0)), - Arguments.of("로그_레벨이 null인 경우", 1L, null, "테스트_로그_데이터", + Arguments.of("로그_레벨이 null인 경우", 앱_키_문자열, null, "테스트_로그_데이터", LocalDateTime.of(2021, 1, 1, 0, 0, 0)), - Arguments.of("로그_레벨이 빈 문자열인 경우", 1L, " ", "테스트_로그_데이터", + Arguments.of("로그_레벨이 빈 문자열인 경우", 앱_키_문자열, " ", "테스트_로그_데이터", LocalDateTime.of(2021, 1, 1, 0, 0, 0)), - Arguments.of("로그_데이터가 null인 경우", 1L, "INFO", null, + Arguments.of("로그_데이터가 null인 경우", 앱_키_문자열, "INFO", null, LocalDateTime.of(2021, 1, 1, 0, 0, 0)), - Arguments.of("로그_데이터가 빈 문자열인 경우", 1L, "INFO", " ", + Arguments.of("로그_데이터가 빈 문자열인 경우", 앱_키_문자열, "INFO", " ", LocalDateTime.of(2021, 1, 1, 0, 0, 0)), - Arguments.of("타임스탬프가 null인 경우", 1L, "INFO", "테스트_로그_데이터", null) + Arguments.of("타임스탬프가 null인 경우", 앱_키_문자열, "INFO", "테스트_로그_데이터", null) ); } } \ No newline at end of file diff --git a/logbat/src/test/java/info/logbat/domain/log/repository/LogRepositoryTest.java b/logbat/src/test/java/info/logbat/domain/log/repository/LogRepositoryTest.java index fca9afe..de6160b 100644 --- a/logbat/src/test/java/info/logbat/domain/log/repository/LogRepositoryTest.java +++ b/logbat/src/test/java/info/logbat/domain/log/repository/LogRepositoryTest.java @@ -6,6 +6,7 @@ import info.logbat.domain.log.domain.enums.Level; import java.time.LocalDateTime; import java.util.Optional; +import java.util.UUID; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -22,6 +23,8 @@ class LogRepositoryTest { @Autowired private LogRepository logRepository; + private static final String 앱_키_문자열 = UUID.randomUUID().toString(); + @DisplayName("Log를 저장할 수 있다.") @Test void saveLog() { @@ -30,7 +33,7 @@ void saveLog() { String 로그_데이터 = "테스트_로그_데이터"; LocalDateTime 타임스탬프 = LocalDateTime.of(2021, 1, 1, 0, 0, 0); - Log 로그 = new Log(1L, 로그_레벨, 로그_데이터, 타임스탬프); + Log 로그 = new Log(앱_키_문자열, 로그_레벨, 로그_데이터, 타임스탬프); // when long 저장된_ID = logRepository.save(로그); @@ -48,7 +51,7 @@ void findLog() { String 로그_데이터 = "테스트_로그_데이터"; LocalDateTime 타임스탬프 = LocalDateTime.of(2021, 1, 1, 0, 0, 0); - long 로그_ID = logRepository.save(new Log(1L, 로그_레벨, 로그_데이터, 타임스탬프)); + long 로그_ID = logRepository.save(new Log(앱_키_문자열, 로그_레벨, 로그_데이터, 타임스탬프)); // when Optional 저장된_로그 = logRepository.findById(로그_ID); @@ -56,8 +59,8 @@ void findLog() { // then assertThat(저장된_로그).isPresent() .get() - .extracting("logId", "applicationId", "level", "logData.value", "timestamp") - .containsExactly(로그_ID, 1L, Level.INFO, "테스트_로그_데이터", + .extracting("logId", "appKey", "level", "data.value", "timestamp") + .containsExactly(로그_ID, 앱_키_문자열, Level.INFO, "테스트_로그_데이터", LocalDateTime.of(2021, 1, 1, 0, 0, 0)); } diff --git a/logbat/src/test/java/info/logbat/domain/project/domain/log/domain/LogTest.java b/logbat/src/test/java/info/logbat/domain/project/domain/log/domain/LogTest.java index 72710e7..b8ef143 100644 --- a/logbat/src/test/java/info/logbat/domain/project/domain/log/domain/LogTest.java +++ b/logbat/src/test/java/info/logbat/domain/project/domain/log/domain/LogTest.java @@ -6,6 +6,7 @@ import info.logbat.domain.log.domain.Log; import info.logbat.domain.log.domain.enums.Level; import java.time.LocalDateTime; +import java.util.UUID; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -13,6 +14,8 @@ @DisplayName("Log 도메인 테스트") class LogTest { + private static final String 앱_키_문자열 = UUID.randomUUID().toString(); + @Nested @DisplayName("새로운 Log 도메인 객체 생성") class CreateNewLog { @@ -21,46 +24,58 @@ class CreateNewLog { @DisplayName("새로 만든 Log 도메인 객체를 만들 수 있다.") void createLog() { // given - Long 어플리케이션_ID = 1L; String 로그_데이터 = "테스트_로그_데이터"; String 로그_레벨 = "INFO"; LocalDateTime 로그_타임스탬프 = LocalDateTime.of(2021, 1, 1, 0, 0, 0); // when - Log log = new Log(어플리케이션_ID, 로그_레벨, 로그_데이터, 로그_타임스탬프); + Log log = new Log(앱_키_문자열, 로그_레벨, 로그_데이터, 로그_타임스탬프); // then assertThat(log) - .extracting("logId", "applicationId", "level", "logData.value", "timestamp") - .containsExactly(null, 1L, Level.INFO, 로그_데이터, 로그_타임스탬프); + .extracting("logId", "appKey", "level", "data.value", "timestamp") + .containsExactly(null, 앱_키_문자열, Level.INFO, 로그_데이터, 로그_타임스탬프); } @Test - @DisplayName("applicationId가 null이면 예외가 발생한다.") + @DisplayName("appKey가 null이면 예외가 발생한다.") void createLogWithNullApplicationId() { // given - Long 어플리케이션_ID = null; String 로그_데이터 = "테스트_로그_데이터"; String 로그_레벨 = "INFO"; LocalDateTime 로그_타임스탬프 = LocalDateTime.of(2021, 1, 1, 0, 0, 0); // when & then - assertThatThrownBy(() -> new Log(어플리케이션_ID, 로그_레벨, 로그_데이터, 로그_타임스탬프)) + assertThatThrownBy(() -> new Log(null, 로그_레벨, 로그_데이터, 로그_타임스탬프)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("appKey는 null이거나 빈 문자열이 될 수 없습니다."); + } + + @Test + @DisplayName("appKey가 비어있으면 예외가 발생한다.") + void createLogWithEmptyApplicationId() { + // given + String 앱_키 = ""; + String 로그_데이터 = "테스트_로그_데이터"; + String 로그_레벨 = "INFO"; + LocalDateTime 로그_타임스탬프 = LocalDateTime.of(2021, 1, 1, 0, 0, 0); + + // when & then + assertThatThrownBy(() -> new Log(앱_키, 로그_레벨, 로그_데이터, 로그_타임스탬프)) .isInstanceOf(IllegalArgumentException.class) - .hasMessage("applicationId는 null이 될 수 없습니다."); + .hasMessage("appKey는 null이거나 빈 문자열이 될 수 없습니다."); } @Test @DisplayName("timestamp가 null이면 예외가 발생한다.") void createLogWithNullTimestamp() { // given - Long 어플리케이션_ID = 1L; String 로그_데이터 = "테스트_로그_데이터"; String 로그_레벨 = "INFO"; LocalDateTime 로그_타임스탬프 = null; // when & then - assertThatThrownBy(() -> new Log(어플리케이션_ID, 로그_레벨, 로그_데이터, 로그_타임스탬프)) + assertThatThrownBy(() -> new Log(앱_키_문자열, 로그_레벨, 로그_데이터, 로그_타임스탬프)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("timestamp는 null이 될 수 없습니다."); } @@ -75,34 +90,48 @@ class CreateExistingLog { void createLogWithLogId() { // given Long 로그_ID = 1L; - Long 어플리케이션_ID = 1L; String 로그_데이터 = "테스트_로그_데이터"; String 로그_레벨 = "INFO"; LocalDateTime 로그_타임스탬프 = LocalDateTime.of(2021, 1, 1, 0, 0, 0); // when - Log log = new Log(로그_ID, 어플리케이션_ID, 로그_레벨, 로그_데이터, 로그_타임스탬프); + Log log = new Log(로그_ID, 앱_키_문자열, 로그_레벨, 로그_데이터, 로그_타임스탬프); // then assertThat(log) - .extracting("logId", "applicationId", "level", "logData.value", "timestamp") - .containsExactly(로그_ID, 1L, Level.INFO, 로그_데이터, 로그_타임스탬프); + .extracting("logId", "appKey", "level", "data.value", "timestamp") + .containsExactly(로그_ID, 앱_키_문자열, Level.INFO, 로그_데이터, 로그_타임스탬프); } @Test - @DisplayName("applicationId가 null이면 예외가 발생한다.") + @DisplayName("appKey가 null이면 예외가 발생한다.") void createLogWithNullApplicationIdWithLogId() { // given Long 로그_ID = 1L; - Long 어플리케이션_ID = null; String 로그_데이터 = "테스트_로그_데이터"; String 로그_레벨 = "INFO"; LocalDateTime 로그_타임스탬프 = LocalDateTime.of(2021, 1, 1, 0, 0, 0); // when & then - assertThatThrownBy(() -> new Log(로그_ID, 어플리케이션_ID, 로그_레벨, 로그_데이터, 로그_타임스탬프)) + assertThatThrownBy(() -> new Log(로그_ID, null, 로그_레벨, 로그_데이터, 로그_타임스탬프)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("appKey는 null이거나 빈 문자열이 될 수 없습니다."); + } + + @Test + @DisplayName("appKey가 비어있으면 예외가 발생한다.") + void createLogWithEmptyApplicationIdWithLogId() { + // given + Long 로그_ID = 1L; + String 앱_키 = ""; + String 로그_데이터 = "테스트_로그_데이터"; + String 로그_레벨 = "INFO"; + LocalDateTime 로그_타임스탬프 = LocalDateTime.of(2021, 1, 1, 0, 0, 0); + + // when & then + assertThatThrownBy(() -> new Log(로그_ID, 앱_키, 로그_레벨, 로그_데이터, 로그_타임스탬프)) .isInstanceOf(IllegalArgumentException.class) - .hasMessage("applicationId는 null이 될 수 없습니다."); + .hasMessage("appKey는 null이거나 빈 문자열이 될 수 없습니다."); } @Test @@ -110,13 +139,12 @@ void createLogWithNullApplicationIdWithLogId() { void createLogWithNullTimestampWithLogId() { // given Long 로그_ID = 1L; - Long 어플리케이션_ID = 1L; String 로그_데이터 = "테스트_로그_데이터"; String 로그_레벨 = "INFO"; LocalDateTime 로그_타임스탬프 = null; // when & then - assertThatThrownBy(() -> new Log(로그_ID, 어플리케이션_ID, 로그_레벨, 로그_데이터, 로그_타임스탬프)) + assertThatThrownBy(() -> new Log(로그_ID, 앱_키_문자열, 로그_레벨, 로그_데이터, 로그_타임스탬프)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("timestamp는 null이 될 수 없습니다."); }