From e76405daf04404a2386b12e5ef77200ce1b275c2 Mon Sep 17 00:00:00 2001 From: Sadturtleman Date: Wed, 26 Aug 2026 00:11:07 +0900 Subject: [PATCH] =?UTF-8?q?refactor(mindrecord):=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=C2=B7=EC=88=98=EC=A0=95=20=EC=9D=91=EB=8B=B5=20DTO=20=EC=9D=98?= =?UTF-8?q?=20=EA=B8=B0=EB=B3=B8=EA=B0=92=EC=9D=84=20=EA=B1=B7=EB=8A=94?= =?UTF-8?q?=EB=8B=A4=20(#789=20=EB=A7=88=EB=AC=B4=EB=A6=AC)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 서버가 항상 채우는 값에 기본값이 있으면 키 누락과 계약 변경이 파싱 실패가 아니라 «정상적인 빈 값» 으로 바뀐다. 특히 isDraft 가 false 로 접히면 임시저장이 정식 답변으로 보인다 — 이 이슈가 든 바로 그 형태다. #789 의 나머지 항목은 그동안 다른 PR 들이 처리했다. 남는 nullable(PATCH 선택 필드, 계약에 없는 imageUrl, 조건부 emotionAnalysis)은 이슈가 «유지» 로 분류한 것들이다. Co-Authored-By: Claude Opus 5 (1M context) --- .../mindrecord/data/dto/DailyQuestionDto.kt | 7 +++- ...DailyQuestionAnswerResponseContractTest.kt | 40 +++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/feature/mindrecord/data/src/main/kotlin/com/afternote/feature/mindrecord/data/dto/DailyQuestionDto.kt b/feature/mindrecord/data/src/main/kotlin/com/afternote/feature/mindrecord/data/dto/DailyQuestionDto.kt index 8937002240..d6ff9d4967 100644 --- a/feature/mindrecord/data/src/main/kotlin/com/afternote/feature/mindrecord/data/dto/DailyQuestionDto.kt +++ b/feature/mindrecord/data/src/main/kotlin/com/afternote/feature/mindrecord/data/dto/DailyQuestionDto.kt @@ -89,6 +89,9 @@ data class TodayDailyQuestionDto( @Serializable data class DailyQuestionAnswerResponseDto( @SerialName("userDailyQuestionId") val userDailyQuestionId: Long, - @SerialName("content") val content: String = "", - @SerialName("isDraft") val isDraft: Boolean = false, + // 기본값을 두지 않는다 — 서버가 항상 채우는 값이라, 기본값이 있으면 키 누락과 계약 + // 변경이 파싱 실패가 아니라 «정상적인 빈 값» 으로 바뀐다. 특히 isDraft 가 false 로 + // 접히면 임시저장이 정식 답변으로 보인다 (#789). + @SerialName("content") val content: String, + @SerialName("isDraft") val isDraft: Boolean, ) diff --git a/feature/mindrecord/data/src/test/java/com/afternote/feature/mindrecord/data/dto/DailyQuestionAnswerResponseContractTest.kt b/feature/mindrecord/data/src/test/java/com/afternote/feature/mindrecord/data/dto/DailyQuestionAnswerResponseContractTest.kt index 7671fb49c5..5b6cb50e7a 100644 --- a/feature/mindrecord/data/src/test/java/com/afternote/feature/mindrecord/data/dto/DailyQuestionAnswerResponseContractTest.kt +++ b/feature/mindrecord/data/src/test/java/com/afternote/feature/mindrecord/data/dto/DailyQuestionAnswerResponseContractTest.kt @@ -1,8 +1,10 @@ package com.afternote.feature.mindrecord.data.dto import com.afternote.core.network.model.BaseResponse +import kotlinx.serialization.MissingFieldException import kotlinx.serialization.json.Json import org.junit.Assert.assertEquals +import org.junit.Assert.assertThrows import org.junit.Test /** @@ -80,4 +82,42 @@ class DailyQuestionAnswerResponseContractTest { assertEquals(true, failed) } + + @Test + fun `isDraft 가 빠지면 정식 답변으로 접히지 않고 실패한다`() { + // false 로 접히면 임시저장이 정식 답변으로 보인다 — 계약 변경이 «정상적인 빈 값» 으로 + // 둔갑하는 자리라 기본값을 두지 않는다 (#789). + val body = + """ + { + "status": 200, "code": 200, "message": "성공", + "data": { "userDailyQuestionId": 19, "content": "응답 계약 실측" } + } + """.trimIndent() + + assertThrows(MissingFieldException::class.java) { + json.decodeFromString( + BaseResponse.serializer(DailyQuestionAnswerResponseDto.serializer()), + body, + ) + } + } + + @Test + fun `content 가 빠져도 빈 문자열로 성공하지 않는다`() { + val body = + """ + { + "status": 200, "code": 200, "message": "성공", + "data": { "userDailyQuestionId": 19, "isDraft": false } + } + """.trimIndent() + + assertThrows(MissingFieldException::class.java) { + json.decodeFromString( + BaseResponse.serializer(DailyQuestionAnswerResponseDto.serializer()), + body, + ) + } + } }