diff --git a/README.md b/README.md
new file mode 100644
index 0000000..e135860
--- /dev/null
+++ b/README.md
@@ -0,0 +1,221 @@
+# ๐ ์ค์๊ฐ ํ์จ [XCP] ๐
+
+
+## โจ ํ๋ก์ ํธ ๊ฐ์
+XChangePass ๋ฐฑ์๋ ์๋น์ค๋ **์ค์ ๊ธ์ต ํธ๋ฌ๋ธ์ํ
๊ฒฝํ**์ ์๊ธฐ ์ํด
+์ค์๊ฐ ํ์จ ์ฐ๋, ๋ฉํฐ ํตํ ์ง๊ฐ, ์์ฝ ์ก๊ธยท์๋ฆผ ๊ธฐ๋ฅ์ ์ง์ ์ค๊ณยท๊ตฌํํ๋ ๊ฒ์ ๋ชฉํ๋ก ํฉ๋๋ค.
+
+## โจ ๊ธฐํ ๋ฐฐ๊ฒฝ
+> ๋จ์ํ ํ์ ๊ธฐ๋ฅ ์ ๊ณต์ ๋์ด,
+> - **์ค์ ๊ธ์ต API ์ฐ๋ ๊ณผ์ **์์ ๋ง์ฃผ์น๋ ๋ณด์ยท์ฑ๋ฅ ์ด์๋ฅผ ํด๊ฒฐํด ๋ณด๊ณ ,
+> - **๋๊ท๋ชจ ํธ๋ํฝ** ์ํฉ์์์ ์บ์ ์ ๋ตยทํธ๋์ญ์
๊ด๋ฆฌ ๊ฒฝํ์ ์์ผ๋ฉฐ,
+> - **์ด์ ํ๊ฒฝ**์์์ ๋ชจ๋ํฐ๋งยท์๋ฆผยท์ ์ฐจ๋ฅผ ์ฒดํํ๋ ๊ฒ์ด ๋ณธ ํ๋ก์ ํธ์ ํต์ฌ ํ์ต ๋ชฉํ์
๋๋ค.
+>
+> ์ด๋ฅผ ํตํด ๋จ์ ๋ฐ๋ชจ๋ฅผ ๋์ด, โํ๋ก๋์
๋ ๋ฒจโ์ ๋ฐฑ์๋ ์ด์ ์ญ๋์ ํ๋ณดํ๊ณ ์ ํฉ๋๋ค.
+
+
+
+
+## โจ ํ๋ก์ ํธ ๊ธฐ๊ฐ
+- **๊ธฐํ ๋ฐ ์ค๊ณ :** 2025.2.17 ~ 2025.2.14
+- **๊ฐ๋ฐ :** 2024.2.15 ~ 2024.12.09
+
+
+
+
+## โจ ์ํคํ
์ฒ ๋ฐ ํต์ฌ ๋ชจ๋
+| ๋ชจ๋ | ์ค๋ช
|
+|--------------------|--------------------------------------------------------------------------------------------------------------------------------------------|
+| ์ธ์ฆยท๊ถํ ๊ด๋ฆฌ | Spring Security + JWT ๊ธฐ๋ฐ ์ธ์ฆยท์ธ๊ฐ, Token Rotate ์ ๋ต |
+| ์นด๋ ๊ด๋ฆฌ | ์นด๋ ๋ฐ๊ธ/์กฐํ/์ํ ๋ณ๊ฒฝ, AES ํคยทIV ์ํธํ (EncryptionData Embeddable) :contentReference[oaicite:0]{index=0}:contentReference[oaicite:1]{index=1} |
+| ์ง๊ฐ(Wallet) ๊ด๋ฆฌ | ์ฌ์ฉ์ ์ง๊ฐ ์์ฑ, ํํ๋ณ ์์ก ์กฐํยท์ฐ์ฐ |
+| ํ์จ ๊ณ์ฐ ์์ง | ์ธ๋ถ API ์ฐ๋(์: Open Exchange Rates), ,๋น๋๊ธฐ ์ฒ๋ฆฌ, ์ค์๊ฐ ํ์จ ์บ์ฑ |
+| ๊ฑฐ๋ ์ฒ๋ฆฌ(Transaction) | ACID ํธ๋์ญ์
๋ณด์ฅ, ์ฅ์ ๋ณต๊ตฌ ๋ก์ง, ๋น๋๊ธฐ ์ฒ๋ฆฌ |
+| ํ์ | ์ค์๊ฐ ํ์จ ๊ธฐ๋ฐ ๋ค์ค ํตํ ๊ฐ ํ์ ์ฒ๋ฆฌ |
+| ์๋ฆผ ์๋น์ค | Slack ์๋ฆผ ๋ฐ์ก |
+
+## โจ ์ฃผ์ ๊ธฐ๋ฅ
+
+### 1. ํ์จ ์ ๋ณด ๋ฐ ํ์
+- **์ค๋ช
**
+ - ์ธ๋ถ ํ์จ API ์ฐ๋(์: Open Exchange Rates), ์ค์๊ฐ ์บ์ฑ(TTL 5๋ถ), CompletableFuture ๊ธฐ๋ฐ ๋น๋๊ธฐ ๊ฐฑ์ ์ฒ๋ฆฌ.
+ - ํ์ ๋ก์ง์ ํธ๋์ญ์
๊ฒฉ๋ฆฌ ์์ค์ ๋ฐ๋ผ ์ต์ ํ (Read Committed > Repeatable Read > Serializable).
+- **์ฑ๋ฅ ํ
์คํธ**
+ - ์๋ต ์๊ฐ: ํ๊ท 70s โ 11~12s (์ฐ๋ ๋ํ + ๋น๋๊ธฐ ์ฒ๋ฆฌ)
+ - TPS ์ฆ๊ฐ: 7 โ 24 โ 48 (๊ฒฉ๋ฆฌ ์์ค: Serializable โ Repeatable Read โ Read Committed)
+
+ํ์ flow ์ฐจํธ ๋ฐ ํธ๋์ น์ ์ฒ๋ฆฌ ํ๋ฆ โถ๏ธ
+
+
+
+- ### **ํ์ ํธ๋์ญ์
์ฒ๋ฆฌ ํ๋ฆ ์ ๋ฆฌ**
+| SQL ์ฒ๋ฆฌ | ์ค๋ช
|
+| --- | --- |
+| TRANSACTION BEGIN | ํธ๋์ญ์
์์ |
+| SELECT * FROM exchange_transaction WHERE transaction_id = #{transactionId} | ๊ฑฐ๋ ๋ด์ญ ์กฐํ (์ํ ํ์ธ: PENDING ์ธ์ง ํ์ธ) |
+| SELECT * FROM wallet WHERE user_id = #{userId} | ์ ์ ์ง๊ฐ ์กฐํ |
+| SELECT * FROM wallet_balance WHERE wallet_id = #{walletId} AND currency = #{fromCurrency} | ์ถ๊ธํ ํํ ์์ก ์กฐํ |
+| IF ์์ก ๋ถ์กฑ THEN INSERT INTO wallet_balance_history (์ถฉ์ ๋ด์ญ) | ์์ก ๋ถ์กฑ ์ ์ถฉ์ ์ฒ๋ฆฌ |
+| SELECT * FROM wallet_balance WHERE wallet_id = #{walletId} AND currency = #{toCurrency} | ์
๊ธํ ํํ ์์ก ์กฐํ |
+| UPDATE wallet_balance SET balance = balance - #{amount} WHERE wallet_id = #{walletId} AND currency = #{fromCurrency} | ์ถ๊ธ ํํ ์์ก ์ฐจ๊ฐ |
+| UPDATE wallet_balance SET balance = balance + #{receivedAmount} WHERE wallet_id = #{walletId} AND currency = #{toCurrency} | ์
๊ธ ํํ ์์ก ์ฆ๊ฐ |
+| UPDATE exchange_transaction SET status = 'COMPLETED' WHERE transaction_id = #{transactionId} | ๊ฑฐ๋ ์ํ ๋ณ๊ฒฝ (์๋ฃ ์ฒ๋ฆฌ) |
+| TRANSACTION COMMIT | ํธ๋์ญ์
์ปค๋ฐ |
+---
+
+
+
+---
+
+### 2. ์ก๊ธ ๋ฐ ๊ฑฐ๋
+- **์ค๋ช
**
+ ์ฌ์ฉ์๊ฐ ๋ค์ค ํตํ ์ก๊ธ ์ฒ๋ฆฌ, ๊ฑฐ๋ ๋ด์ญ ๊ธฐ๋ก, ACID ํธ๋์ญ์
๋ณด์ฅ, ๋ชจ๋ํ๋ ๊ฑฐ๋ ์ฒ๋ฆฌ ๋ก์ง
+
+
+
+ ๊ฑฐ๋์์คํ
์ฃผ์ ํ๋ฆ โถ๏ธ
+
+ 
+
+
+
+- **์ฑ๋ฅ ํ
์คํธ**
+ - ์๋๋ฆฌ์ค : ๋ก๊ทธ์ธ โ ์ถฉ์ โ ์ถ๊ธ โ ์ก๊ธ โ ์์ก ์กฐํ โ ๊ฑฐ๋๋ด์ญ ์กฐํ
+ - ๋์์ฑ ํ
์คํธ: 50 โ 100 โ 200 ์ ์ง โ 50 โ 10๋ช
๊น์ง ์ ์ง ์ฆ๊ฐ/๊ฐ์ ์๋๋ฆฌ์ค (์ด 5๋ถ ํ
์คํธ)
+ - ํ๊ท ์์ฒญ ์๋ (Avg. Req/sec) : ์ฝ 139 req/s, ์ต๋ 368 req/s
+ - Errors per Second = 0
+ - ์๋ต ์๊ฐ (http_req_duration) : ํ๊ท : 588ms, ์ต๋: 4.40์ด, P90: 1.36์ด, P95: 1.70์ด, ์ต์: 1.87ms
+ - ์์ฒญ ๋ธ๋กํน ์๊ฐ (http_req_blocked) : ๊ฑฐ์ ์์ (ํ๊ท 0.03ms)
+ - ์ฒดํฌ ์ฑ๊ณต๋ฅ (Checks Per Second) : ์ด 7015๊ฑด ์ค ๊ฑฐ๋๋ด์ญ ๋ฐ ๋ก๊ทธ์ธ ๋ฑ ๊ฒ์ฆ ํญ๋ชฉ 99% ์ด์ ์ฑ๊ณต
+- **ํ
์คํธ**
+ - ๋จ์ ํ
์คํธ (Unit Test)
+ - **๋์**
+ - ์ง๊ฐ ๋ก์ง์ ํต์ฌ ๊ธฐ๋ฅ์ธ **์์ก ์ฒ๋ฆฌ ๋ก์ง**
+ - ํธ๋์ญ์
๋ฉ์์ง ์์ฑ/์๋น ๋ก์ง, ์ฌ๋ ์๋ฆผ ์ ์ก ๋ฑ
+
+ - **์ฃผ์ ๋ด์ฉ**
+ - ์ถฉ์ (Deposit), ์ถ๊ธ(Withdraw), ์ก๊ธ(Transfer) ๊ธฐ๋ฅ์ ๋ด๋ถ ๋ก์ง ๊ฒ์ฆ
+ - ์คํจ ์กฐ๊ฑด ๋ฐ์ ์ ์์ธ ์ฒ๋ฆฌ ๊ฒ์ฆ
+ - `@MockBean` ๋ฐ ๋ด๋ถ ๊ฐ์ฒด ์ฃผ์
์ ํตํ ๋ก์ง ๋จ์ ๋จ๋
ํ
์คํธ
+ - ์ฌ๋ ์๋ฆผ ๋ฑ ์ธ๋ถ ์ฐ๋ ์์กด์ฑ์ ์ ๊ฑฐํ ๋ฉ์์ง ์ปจ์๋จธ ํ
์คํธ
+
+ - โ
ํตํฉ ํ
์คํธ (Integration Test)
+
+ > Testcontainers ๊ธฐ๋ฐ PostgreSQL, RabbitMQ ํ๊ฒฝ์์ ์ค์ ์๋น์ค ํ๋ฆ์ ๊ฒ์ฆํ๋ E2E ํตํฉ ํ
์คํธ ์ํ
+
+ - **ํ๊ฒฝ**
+ - `PostgreSQL`, `RabbitMQ` ๋์ปค ์ปจํ
์ด๋ ๊ธฐ๋ฐ ๊ตฌ์ฑ
+ - `SlackNotifier`๋ `@MockBean` ์ฒ๋ฆฌ
+
+ - **๊ฒ์ฆ ํญ๋ชฉ**
+ - ์ฌ์ฉ์ ์ง๊ฐ ์์ฑ โ ์ถฉ์ โ ์ก๊ธ โ ์์ก ํ์ธ๊น์ง์ ์ ์ฒด ํ๋ฆ
+ - ๋์ ์ก๊ธ, ์ก๊ธ ๋์ค ์ถ๊ธ, ์ถฉ์ ๋์ค ์ก๊ธ ๋ฑ **๊ฒฝ์ ์ํฉ ์ฒ๋ฆฌ**
+ - ํธ๋์ญ์
๊ธฐ๋ก ์์ฑ ๋ฐ ๊ฑฐ๋๋ด์ญ ์กฐํ ๊ธฐ๋ฅ
+ - ์คํจ ๋ฉ์์ง โ DLQ โ Slack ์๋ฆผ ์ ์ก ์๋๋ฆฌ์ค ๊ฒ์ฆ
+
+ - **์ฃผ์ ์๋๋ฆฌ์ค**
+
+ | ์๋๋ฆฌ์ค | ์ค๋ช
|
+ |----------|------|
+ | โ
์ ์ ์ก๊ธ ์ฒ๋ฆฌ | ์ก๊ธ ํ ์ก/์์ ์ ์์ก ๋ฐ์ ํ์ธ |
+ | โ ์์ก ๋ถ์กฑ ์์ธ | ์์ธ ๋ฐ์ ๋ฐ ํธ๋์ญ์
์ ์ฅ ์๋จ |
+ | ๐ ๋๋ ๋์ ์ก๊ธ | 100๋ช
์ก๊ธ ์ ์ผ๊ด์ฑ ์ ์ง |
+ | โ ๏ธ ์ถฉ๋ ์ํฉ ํ
์คํธ | ์ก๊ธ โ ์ถ๊ธ, ์ถฉ์ โ ์ก๊ธ ๋์ ๋ฐ์ ์ ์ฒ๋ฆฌ ํ์ธ |
+ | ๐ค DLQ ์ฒ๋ฆฌ | ์คํจ ๋ฉ์์ง โ Slack ์๋ฆผ ์ ์ก๊น์ง ํ๋ฆ ๊ฒ์ฆ |
+ | ๐ ๊ฑฐ๋๋ด์ญ ํํฐ๋ง | ํธ๋์ญ์
ํ์
๋ณ ์กฐํ ๊ธฐ๋ฅ ํ์ธ |
+
+---
+
+### 3. ์นด๋ ๊ด๋ฆฌ ๋ฐ ์ ๋ณด ์ํธํ
+- **์ค๋ช
**
+ - `CardService.generatePhysicalCard(userId)`
+ - ๋ฌผ๋ฆฌ(์ค๋ฌผ) ์นด๋ ๋ฐ๊ธ
+ - KMS ๊ธฐ๋ฐ RSAEncryption์ผ๋ก AES ํค ์๋ณตํธํ โ `EncryptionData` Embeddable์ ์ํธํ๋ AES ํคยทIV ์ ์ฅ
+ - `CardService.getDetailedCardInfo(cardId)`
+ - Redis ์บ์ ์กฐํ
+ - ์บ์์ ์์ผ๋ฉด RSAEncryption์ผ๋ก AES ํค ๋ณตํธํ โ AESEncryption์ผ๋ก ์นด๋๋ฒํธยทCVC ๋ณตํธํ โ Redis์ ์ ์ฅ
+ - `CardService.changeCardStatus(userId, request)`
+ - DB ์
๋ฐ์ดํธ + Redis ์บ์ ๋์ ๋ฐ์
+
+### ์ํ์ค ๋ค์ด์ด๊ทธ๋จ
+
+
+์นด๋ ๊ด๋ฆฌ ์ฃผ์ ํ๋ฆ โถ๏ธ
+
+#### 1) ์ค๋ฌผ ์นด๋ ๋ฐ๊ธ ์ํ์ค
+
+
+#### 2) ์นด๋ ์์ธ ์กฐํ ์ํ์ค
+
+
+
+- **๐์ฑ๋ฅ ํ
์คํธ**
+ - **์ํธํ/๋ณตํธํ ์ฒ๋ฆฌ๋**: 1,000๊ฑด/sec โ ํ๊ท ์ง์ฐ โค 10ms
+ - **Redis ์บ์ ์ ์ค๋ฅ **: 100์กฐํ ์ค โฅ 90% (TTL 5๋ถ)
+ - **์ปจํธ๋กค๋ฌ ์๋ต ์๋** (MockMvc ๊ธฐ์ค)
+ - POST `/api/v1/card/physical`, PUT `/api/v1/card/status`: โค 50ms
+ - GET `/api/v1/card`, `/api/v1/card/{cardId}`: โค 30ms
+
+- **๐จํ
์คํธ**
+ - **โ
์ปจํธ๋กค๋ฌ ๋จ์ ํ
์คํธ** (`CardControllerTest`)
+ - `์ค๋ฌผ์นด๋๋ฐ๊ธ_์ฑ๊ณต` (POST `/api/v1/card/physical` โ 201 Created)
+ - `์นด๋์ํ๋ณ๊ฒฝ_์ฑ๊ณต` (PUT `/api/v1/card/status` โ 204 No Content)
+ - `๋ณด์ ์นด๋๋ชฉ๋ก์กฐํ_์ฑ๊ณต` (GET `/api/v1/card` โ 200 OK)
+ - `์นด๋์์ธ์ ๋ณด์กฐํ_์ฑ๊ณต` (GET `/api/v1/card/{cardId}` โ 200 OK)
+
+ - **โ
์๋น์ค ํตํฉ ํ
์คํธ** (`CardServiceTest` extends `RedisTestBase`)
+ - `verifyPhysicalCardIssuance`: DB์ ์ค๋ฌผ ์นด๋ ์ ์ ๋ฐ๊ธ ํ์ธ
+ - `verifyKeyDecryptionAndRedisStorage`:
+ - RSAEncryption์ผ๋ก AES ํค ๋ณตํธํ
+ - AESEncryption์ผ๋ก ์นด๋๋ฒํธยทCVC ๋ณตํธํ
+ - Redis ์บ์ ์ ์ฅ ํ์ธ
+ - `changeCardStatus_shouldUpdateBothDatabaseAndRedisCache`:
+ - DB ์ํ ๋ณ๊ฒฝ
+ - Redis ์บ์ ์ํ ๋๊ธฐํ
+
+ - **โ
ํ
์คํธ ์คํ**
+ - JUnit5, Mockito, Spring Boot Test, MockMvc
+ - Testcontainers Embedded Redis
+
+
+
+
+## โจ ๊ธฐ์ ์คํ
+___
+
+
+
+
+
+
+
+
+
+
+
+
+## โจ ๊ฐ๋ฐ ๋ฌธ์
+
+ERD
+
+
+
+
+์ปจ๋ฒค์
+
+
+- [ํ ๊ท์น](https://silky-toothbrush-191.notion.site/ee1575c5d056473f83d9f56f40edaa47)
+- [๊ณตํต ์ปค๋ฐ ์ปจ๋ฒค์
](https://silky-toothbrush-191.notion.site/3903032f148543b685d3de474249d31f)
+- [๋ฒก์๋ ์ฝ๋ ์ปจ๋ฒค์
](https://silky-toothbrush-191.notion.site/70565c77e3b34b38bb8d2d56ca7a6a54)
+
+
+
+
+## โจ ํ ์๊ฐ
+
+| BE | BE | BE |
+|:----------------------------------------------------------:|:----------------------------------------------------------:|:----------------------------------------------------------:|
+|  |  |  |
+| Team Leader | Developer | Developer |
+| [๊ฐ์์](https://github.com/Si-rauis) | [์ด์ํ](https://github.com/CryingPerson) | [์ด์ฉ์ค](https://github.com/usingjun) |
+| ์นด๋ ๊ด๋ฆฌ / ์ ์ CRUD /
๊ธ์ต ์ ๋ณด ์ํธํ / Jira ์ฐ๋ | ์ค์๊ฐ ํ์จ ์ ๋ณด/
๋์์ฑ ์ ์ด ํ์ | ๊ฑฐ๋ ์์คํ
(์ก๊ธ, ์ถฉ์ , ์ถ๊ธ) / ์ํ๋ฆฌํฐ ๊ตฌ์ฑ(๋ก๊ทธ์ธ)
/์ง๊ฐ ๊ฑฐ๋๋ด์ญ(์ฅ์ ๋ณต๊ตฌ, ์๋ฆผ) |
\ No newline at end of file
diff --git a/docs/Copy_of_XCP_1.png b/docs/Copy_of_XCP_1.png
new file mode 100644
index 0000000..65a48f5
Binary files /dev/null and b/docs/Copy_of_XCP_1.png differ
diff --git a/docs/XCP.png b/docs/XCP.png
new file mode 100644
index 0000000..791d8f0
Binary files /dev/null and b/docs/XCP.png differ
diff --git a/docs/XCP_drawio.png b/docs/XCP_drawio.png
new file mode 100644
index 0000000..7dd7058
Binary files /dev/null and b/docs/XCP_drawio.png differ
diff --git a/docs/flow/exchangeFlowChart.png b/docs/flow/exchangeFlowChart.png
new file mode 100644
index 0000000..7940f51
Binary files /dev/null and b/docs/flow/exchangeFlowChart.png differ
diff --git a/docs/sequence/card-issuance-sequence.png b/docs/sequence/card-issuance-sequence.png
new file mode 100644
index 0000000..55081d6
Binary files /dev/null and b/docs/sequence/card-issuance-sequence.png differ
diff --git a/docs/sequence/card-retrieval-sequence.png b/docs/sequence/card-retrieval-sequence.png
new file mode 100644
index 0000000..46953cb
Binary files /dev/null and b/docs/sequence/card-retrieval-sequence.png differ
diff --git a/src/main/java/bumblebee/xchangepass/domain/card/service/CardService.java b/src/main/java/bumblebee/xchangepass/domain/card/service/CardService.java
index 8f28f58..45c467c 100644
--- a/src/main/java/bumblebee/xchangepass/domain/card/service/CardService.java
+++ b/src/main/java/bumblebee/xchangepass/domain/card/service/CardService.java
@@ -105,6 +105,8 @@ public void generatePhysicalCard(Long userId) {
.build();
cardRepository.save(mobileCard);
+
+ existUser.getWallet().getCards().add(mobileCard);
}catch (CommonException e) {
throw e;
}catch (Exception e) {
diff --git a/src/test/java/bumblebee/xchangepass/domain/card/controller/CardControllerTest.java b/src/test/java/bumblebee/xchangepass/domain/card/controller/CardControllerTest.java
index b3ff9d1..8a96a9f 100644
--- a/src/test/java/bumblebee/xchangepass/domain/card/controller/CardControllerTest.java
+++ b/src/test/java/bumblebee/xchangepass/domain/card/controller/CardControllerTest.java
@@ -7,6 +7,7 @@
import bumblebee.xchangepass.domain.card.entity.CardStatus;
import bumblebee.xchangepass.domain.card.entity.CardType;
import bumblebee.xchangepass.domain.card.service.CardService;
+import bumblebee.xchangepass.global.security.jwt.CustomUserDetails;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
@@ -17,12 +18,16 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.http.MediaType;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.test.context.support.WithMockUser;
+import org.springframework.security.test.context.support.WithUserDetails;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.web.servlet.MockMvc;
import java.time.LocalDateTime;
import java.util.Collections;
+import java.util.List;
import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
@@ -33,8 +38,8 @@
* ์ปจํธ๋กค๋ฌ ๋จ์ ํ
์คํธ
*/
@SpringBootTest
-@AutoConfigureMockMvc
@ActiveProfiles("test")
+@AutoConfigureMockMvc
@Import(TestUserInitializer.class)
class CardControllerTest {
@@ -47,8 +52,22 @@ class CardControllerTest {
@Autowired
private ObjectMapper objectMapper;
+ @TestConfiguration
+ static class MockSecurityConfig {
+ @Bean
+ public UserDetailsService customUserDetailsService() {
+ // username("1") ์์ฒญ์ด ๋ค์ด์ค๋ฉด CustomUserDetails๋ฅผ ๋ฐํํ๋๋ก
+ return username -> new CustomUserDetails(
+ 1L,
+ username,
+ "",
+ "ROLE_USER"
+ );
+ }
+ }
+
@Test
- @WithMockUser(username = "1")
+ @WithUserDetails(value = "1", userDetailsServiceBeanName = "customUserDetailsService")
void ์ค๋ฌผ์นด๋๋ฐ๊ธ_์ฑ๊ณต() throws Exception {
doNothing().when(cardService).generatePhysicalCard(1L);
@@ -61,7 +80,7 @@ class CardControllerTest {
}
@Test
- @WithMockUser(username = "1")
+ @WithUserDetails(value = "1", userDetailsServiceBeanName = "customUserDetailsService")
void ์นด๋์ํ๋ณ๊ฒฝ_์ฑ๊ณต() throws Exception {
ChangeCardStatusRequest request = ChangeCardStatusRequest.builder()
.cardType(CardType.PHYSICAL)
@@ -82,7 +101,7 @@ class CardControllerTest {
}
@Test
- @WithMockUser(username = "1")
+ @WithUserDetails(value = "1", userDetailsServiceBeanName = "customUserDetailsService")
void ๋ณด์ ์นด๋๋ชฉ๋ก์กฐํ_์ฑ๊ณต() throws Exception {
BasicCardInfoResponse cardInfoResponse = BasicCardInfoResponse.builder()
.cardId(1L)
@@ -102,7 +121,7 @@ class CardControllerTest {
}
@Test
- @WithMockUser(username = "1")
+ @WithUserDetails(value = "1", userDetailsServiceBeanName = "customUserDetailsService")
void ์นด๋์์ธ์ ๋ณด์กฐํ_์ฑ๊ณต() throws Exception {
Long cardId = 1L;
DetailedCardInfoResponse cardInfoResponse = DetailedCardInfoResponse.builder()
diff --git a/src/test/java/bumblebee/xchangepass/domain/card/service/CardServiceTest.java b/src/test/java/bumblebee/xchangepass/domain/card/service/CardServiceTest.java
index 7e05941..5209cd2 100644
--- a/src/test/java/bumblebee/xchangepass/domain/card/service/CardServiceTest.java
+++ b/src/test/java/bumblebee/xchangepass/domain/card/service/CardServiceTest.java
@@ -24,7 +24,6 @@
import org.springframework.transaction.annotation.Transactional;
import javax.crypto.SecretKey;
-
import java.util.List;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
@@ -56,7 +55,11 @@ public class CardServiceTest extends RedisTestBase {
void verifyPhysicalCardIssuance(){
Long userId = 1L;
- cardService.generatePhysicalCard(userId);
+ try {
+ cardService.generatePhysicalCard(userId);
+ }catch (Exception e){
+ System.out.println(e.getMessage());
+ }
User user = userRepository.findByUserId(userId)
.orElseThrow(ErrorCode.USER_NOT_FOUND::commonException);
@@ -109,7 +112,7 @@ void verifyKeyDecryptionAndRedisStorage() {
@Test
@DisplayName("์นด๋ ์ํ ๋ณ๊ฒฝ ์ DB์ Redis ๋์ ๋ฐ์")
void changeCardStatus_shouldUpdateBothDatabaseAndRedisCache() {
- Long userId = 2L;
+ Long userId = 3L;
cardService.generatePhysicalCard(userId);
List cardInfo = cardService.getBasicCardInfo(userId);