{"id":4528,"date":"2026-09-02T07:30:00","date_gmt":"2026-09-01T22:30:00","guid":{"rendered":"https:\/\/litcoder.com\/?p=4528"},"modified":"2026-08-12T09:36:27","modified_gmt":"2026-08-12T00:36:27","slug":"rust-unittest%eb%a5%bc-%ec%9c%84%ed%95%9c-%ec%9d%98%ec%a1%b4%ec%84%b1-%ea%b2%a9%eb%a6%ac","status":"publish","type":"post","link":"https:\/\/litcoder.com\/?p=4528","title":{"rendered":"Rust unittest\ub97c \uc704\ud55c \uc758\uc874\uc131 \uaca9\ub9ac"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">\ub2e4\ud589\ud788\ub3c4 \uc6b0\ub9ac\ub294 unittest\uc758 \uc720\uc6a9\ud568 \uc798 \uc54c\ub824\uc9c4 \uc2dc\ub300\uc5d0 \uc0b4\uace0 \uc788\uae30\uc5d0 \ub354 \uc774\uc0c1 unittest\ub97c \uc9c0\uc6d0\ud558\ub294 \ud504\ub85c\uadf8\ub798\ubc0d \uc5b8\uc5b4\ub97c \ud2b9\ubcc4\ud558\uac8c \ubc1b\uc544\ub4e4\uc774\uc9c0 \uc54a\ub294\ub2e4. Rust\ub294 \ube44\uad50\uc801 \ucd5c\uc2e0 \uc5b8\uc5b4\uc778 \ub9cc\ud07c \uc774\ub7ec\ud55c \uc694\uad6c\uc0ac\ud56d\ub4e4\uc744 \uc801\uadf9\uc801\uc73c\ub85c \ubc1b\uc544\ub4e4\uc5ec \ubd80\uac00\uc801\uc778 \ud504\ub808\uc784\uc6cc\ud06c\uc758 \ub3c4\uc6c0 \uc5c6\uc774\ub3c4 \uc5b8\uc5b4 \uc790\uccb4\uc5d0\uc11c \uae30\ubcf8\uc801\uc778 unittest\uac00 \uc798 \uc9c0\uc6d0\ub41c\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ub2e4\ub9cc, Rust\ub294 \uc0c1\uc18d\uc744 \uc9c0\uc6d0\ud558\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0 Python, Java, C++ \uac19\uc740 \uac1d\uccb4\uc9c0\ud5a5 \uc5b8\uc5b4\uc5d0\uc11c \uc758\uc874\uc131\uc744 \uaca9\ub9ac \ud560 \ub54c \uc0ac\uc6a9\ub418\ub294 method overriding\uc774\ub098 object patching\uc744 \uc0ac\uc6a9\ud560 \uc218\ub294 \uc5c6\ub2e4. \uc77c\ubc18\uc801\uc778 \ubc29\ubc95\uc73c\ub85c mock injection\uc744 \uc218\ud589\ud560 \uc218 \uc5c6\ub2e4\uba74 \ub9e4\ubc88 \ubaa8\ub4e0 \uc758\uc874\uc131\uc744 \ubb3c\ub824 \ub193\uace0 test\ub97c \uc218\ud589\ud574\uc57c\ub9cc \ud560\uae4c?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ub2e4\ud589\ud788\ub3c4 pytest\uc758 mocker patch \ub9cc\ud07c \uc720\uc5f0\ud558\uac8c\ub294 \uc544\ub2c8\uc9c0\ub9cc, Rust\uc5d0\uc11c\ub3c4 trait + automock\uc758 \uc870\ud569\uc73c\ub85c \uc758\uc874\uc131\uc744 \uaca9\ub9ac\ud574\uc11c unittest\ub97c \uc791\uc131\ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Trait<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Trait\uc740 \uac1d\uccb4\uac04\uc758 \uacc4\uc57d\uc744 \uc815\uc758\ud55c\ub2e4\ub294 \uc810\uc5d0\uc11c \ub2e4\ub978 \uc5b8\uc5b4\uc758 interface\uc640 \ub2ee\uc740 \uc810\uc774 \ub9ce\ub2e4. \uc608\ub97c \ub4e4\uc5b4 \ub370\uc774\ud130 \ubca0\uc774\uc2a4\uc5d0 \uc811\uadfc\ud574\uc11c \uacc4\uc88c\uc758 \uc794\uace0\ub97c \ud655\uc778\ud558\uace0 \uc5c5\ub370\uc774\ud2b8\ud558\ub294 \ub2e4\uc74c\uacfc \uac19\uc740 \uac04\ub2e8\ud55c Database trait\uc744 \uc0dd\uac01\ud574 \ubcf4\uc790.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"rust\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">pub trait Database {\n    \/\/ \uc0ac\uc6a9\uc790\uc758 \uc794\uace0\ub97c \ubc18\ud658, \uc624\ub958\uac00 \ubc1c\uc0dd\ud558\uba74 \uc5d0\ub7ec \uba54\uc138\uc9c0 \ubc18\ud658.\n    fn get_user_balance(&amp;self, user_id: u64) -> Result&lt;u64, String>;\n\n    \/\/ \uc0ac\uc6a9\uc790\uc758 \uc794\uace0\ub97c amount\ub85c \uc5c5\ub370\uc774\ud2b8.\n    fn update_user_balance(&amp;mut self, user_id: u64, amount: u64) -> Result&lt;(), String>;\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\uc6b0\ub9ac\ub294 \uc2e4\uc81c \uad6c\ud604\uc774 \uc5c6\ub294 \uc774 trait\uc744 \uc774\uc6a9\ud574\uc11c unittest\ub97c \uc704\ud55c mock inject\uc744 \uc218\ud589\ud560 \uac83\uc774\ub2e4. \uc989, \uc774 trait\uc744 \ubc1b\uc544\ub4e4\uc774\ub294 &#8220;\uc0ac\uc6a9\uc790&#8221;\ub97c \uc815\uc758\ud55c \ub2e4\uc74c, \ud14c\uc2a4\ud2b8\ub97c \uc704\ud574\uc11c\ub294 mock\uc73c\ub85c \uad6c\uc131\ub41c \uac1d\uccb4\ub97c \ub118\uaca8\uc8fc\uc5b4\uc11c \ud14c\uc2a4\ud2b8\ub97c \uc218\ud589\ud558\uace0, \uc2e4\uc81c\ub85c Database trait\uc744 \uc815\uc758\ud558\ub294 \ud504\ub85c\ub355\uc158 \ucf54\ub4dc\ub294 \ub098\uc911\uc5d0 \uc815\uc758\ud574\uc11c \ub118\uaca8\uc8fc\ub824\ub294 \uac83\uc774\ub2e4.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">WalletService &#8211; Database Trait \uc0ac\uc6a9\uc790<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\uc774 trait\uc744 \ubc1b\uc544\ub4e4\uc774\ub294 &#8220;\uc0ac\uc6a9\uc790&#8221;\uc778 <code>WalletService<\/code>\uac1d\uccb4\ub294 \uc774 database trait\uc5d0 interface\ub97c \ud1b5\ud574 \uc811\uadfc\ud558\uac8c \ub41c\ub2e4. \ub2e4\uc74c\uc758 \ucf54\ub4dc\uc5d0\uc11c \ucc98\ub7fc \ucd9c\uae08 \uae30\ub2a5 \uad6c\ud604\uc744 \uc704\ud574 database\ub97c \uc811\uadfc\ud55c\ub2e4.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"rust\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">pub struct WalletService&lt;DB: Database> {\n    db: DB,\n}\n\nimpl&lt;DB: Database> WalletService&lt;DB> {\n    pub fn new(db: DB) -> Self {\n        Self { db }\n    }\n    \/\/ \ucd9c\uae08\n    pub fn withdraw(&amp;mut self, user_id: u64, amount: u64) -> Result&lt;u64, String> {\n        let current_balance = self.db.get_user_balance(user_id)?;\n        if current_balance &lt; amount {\n            return Err(String::from(\"\uc794\uc561\uc774 \ubd80\uc871\ud569\ub2c8\ub2e4.\"));\n        }\n        let new_balance = current_balance - amount;\n        self.db.update_user_balance(user_id, new_balance)?;\n        Ok(new_balance)\n    }\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><code><code data-enlighter-language=\"rust\" class=\"EnlighterJSRAW\">fn new(db: DB)<\/code><\/code>\uc5d0\uc11c \uc815\uc758\ub41c \uac83 \ucc98\ub7fc, \uc774 \uac1d\uccb4\ub294 Database trait\uc744 \uad6c\ud604\ud558\ub294 \ubaa8\ub4e0 \uac1d\uccb4\ub97c \ubc1b\uc744 \uc218 \uc788\ub2e4. \uc774\uc81c \uc6b0\ub9ac\ub294 Database trait\uc744 \uad6c\ud604\ud558\ub294 mock \uac1d\uccb4\ub97c \uc774 \ud568\uc218\uc5d0 \ub118\uaca8\uc8fc\uba74 \ub41c\ub2e4.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Mockall Crate &#8211; Automock<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\uc6b0\ub9ac\uac00 WalletService\uc758 database \uc811\uadfc\uc5d0 \ub300\ud55c \ub3d9\uc791\uc744 \ud14c\uc2a4\ud2b8\ud558\uae30 \uc704\ud574 \uc9c1\uc811 Database trait\uc744 \uad6c\ud604\ud558\ub294 mock \uac1d\uccb4\ub97c \uad6c\ud604\ud560 \uc218\ub3c4 \uc788\uaca0\uc9c0\ub9cc, Mockall crate\uc758 Automock\uc740 \uc774 \uacfc\uc815\uc744 \ud3b8\ub9ac\ud558\uac8c \uc218\ud589\ud560 \uc218 \uc788\ub3c4\ub85d \ub3c4\uc640 \uc900\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uba3c\uc800 Mockall crate\uc744 \uc758\uc874\uc131 \ubaa9\ub85d\uc5d0 \ucd94\uac00\ud574 \uc900\ub2e4.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"bash\" data-enlighter-theme=\"dracula\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"false\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">cargo add mockall<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\uc55e\uc11c \ub9cc\ub4e4\uc5c8\ub358 Database trait\uc5d0 unittest \ud658\uacbd\uc5d0\uc11c\ub9cc mock \uac1d\uccb4\ub97c \uc0dd\uc131\ud558\ub3c4\ub85d <code><code data-enlighter-language=\"rust\" class=\"EnlighterJSRAW\">#[cfg_attr(test, automock)]<\/code><\/code> \ub9e4\ud06c\ub85c\ub97c \uc120\uc5b8\ud574\uc900\ub2e4.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"rust\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">use mockall::automock;\n\n\n#[cfg_attr(test, automock)]\npub trait Database {\n    \/\/ \uc0ac\uc6a9\uc790\uc758 \uc794\uace0\ub97c \ubc18\ud658, \uc624\ub958\uac00 \ubc1c\uc0dd\ud558\uba74 \uc5d0\ub7ec \uba54\uc138\uc9c0 \ubc18\ud658.\n    fn get_user_balance(&amp;self, user_id: u64) -> Result&lt;u64, String>;\n\n    \/\/ \uc0ac\uc6a9\uc790\uc758 \uc794\uace0\ub97c amount\ub85c \uc5c5\ub370\uc774\ud2b8.\n    fn update_user_balance(&amp;mut self, user_id: u64, amount: u64) -> Result&lt;(), String>;\n}<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Mock Object\ub97c \uc774\uc6a9\ud55c Unittest\uc791\uc131<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\uba3c\uc800 \ucd9c\uae08\uc744 \uc2dc\ub3c4 \ud560 \ub54c, \uc608\uae08 \uc870\ud68c\uc5d0\uc11c \ucda9\ubd84\ud55c \uae08\uc561\uc774 \ubc18\ud658\ub418\uc5b4 \uc131\uacf5\ud558\ub294 \uacbd\uc6b0\ub97c \ud14c\uc2a4\ud2b8 \ud574\ubcf4\uc790.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"rust\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"true\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">#[test]\nfn test_withdraw_success() {\n    \/\/ mockall\uc774 \uc790\ub3d9 \uc0dd\uc131\ud55c MockDatabase \uad6c\uc870\uccb4 \uc0ac\uc6a9\n    let mut mock_db = MockDatabase::new();\n\n    \/\/ Expectation(\uae30\ub300\uce58) \uc124\uc815\n    \/\/ get_user_balance\ub294 \uc778\uc790\ub85c \uc0ac\uc6a9\uc790 id\uc778 1\uc744 \ubc1b\uc544 \uc794\uc561 1000000\uc744 \ubc18\ud658, 1\ubc88 \ud638\ucd9c\ub418\uc5b4\uc57c \ud568.\n    mock_db.expect_get_user_balance()\n        .with(mockall::predicate::eq(1))\n        .times(1)\n        .returning(|_| Ok(1000000));\n\n    \/\/ update_user_balance\ub294 \uc778\uc790\ub85c \uc0ac\uc6a9\uc790 id '1'\uacfc \uc794\uc561 '500000'\uc744 \ubc1b\uc544 \uc131\uacf5(())\uc744 \ubc18\ud658, 1\ubc88 \ud638\ucd9c\ub418\uc5b4\uc57c \ud568.\n    mock_db.expect_update_user_balance()\n        .with(mockall::predicate::eq(1), mockall::predicate::eq(500000))\n        .times(1)\n        .returning(|_, _| Ok(()));\n\n    \/\/ Database trait \uc0ac\uc6a9\uc790\uc778 WalletService\uc5d0 mock injection\n    let mut service = WalletService::new(mock_db);\n\n    \/\/ \uc2e4\ud589 \ubc0f \uac80\uc99d\n    let result = service.withdraw(1, 500000);\n    assert!(result.is_ok());\n    assert_eq!(result.unwrap(), 500000);\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">4\ubc88\uc9f8 \uc904\uc744 \ubcf4\uba74 <code>MockDatabase::new()<\/code>\ub85c Database trait\uc758 mock \uac1d\uccb4\ub97c \uc0dd\uc131\ud558\ub294\ub370, \uc774\ub807\uac8c \uc0dd\uc131\ub41c \uac1d\uccb4\ub294 <strong>automock<\/strong> \ub355\ubd84\uc5d0 \uc5b4\ub5a4 \ud568\uc218\uac00 \uba87 \ubc88 \ud638\ucd9c \ub418\uc5c8\ub294\uc9c0 \uc5ec\ubd80\uc640 \ubc1b\uc740 \uc778\uc790 \uac12 \uac80\uc0ac \uadf8\ub9ac\uace0 \ud574\ub2f9 \ubd88\ub824\uc9c4 \ud568\uc218\uac00 \ubc18\ud658\ud560 \uac12\uc744 \uc9c0\uc815\ud574 \uc8fc\ub294 \ud568\uc218\ub4e4\uc774 \uc790\ub3d9\uc73c\ub85c \ud3ec\ud568\ub41c\ub2e4. \uc704 \ucf54\ub4dc\uc5d0\uc11c 6\ubc88\uc9f8 \uc904\ubd80\ud130 16\ubc88\uc9f8 \uc904\uae4c\uc9c0\uc758 \ub0b4\uc6a9\uc774 \uc774\ub807\uac8c \uc790\ub3d9\uc73c\ub85c \uc0dd\uc131\ub41c mock \uac1d\uccb4\uc5d0\uc11c \uc9c0\uc6d0\ud574 \uc8fc\ub294 \ud568\uc218\ub4e4\uc744 \ud1b5\ud574 expectation\uc744 \uc124\uc815\ud558\ub294 \uc8fc\ub294 \ubd80\ubd84\uc774\ub2e4.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>expect_&lt;\ud568\uc218\uba85&gt;()<\/strong>: trait\uc758 \uba64\ubc84\uc778 \ud568\uc218\uac00 \ud638\ucd9c\ub418\uc9c0 \uc54a\uc73c\uba74 \ud14c\uc2a4\ud2b8\uac00 \uc2e4\ud328\ud55c\ub2e4.<\/li>\n\n\n\n<li><strong>with()<\/strong>: \ud574\ub2f9 \ud568\uc218\uac00 \ud638\ucd9c\ub420 \ub54c \ub118\uaca8\ubc1b\uc740 \uc778\uc790 \uac12\uc744 \ud655\uc778\ud55c\ub2e4.<\/li>\n\n\n\n<li><strong>times()<\/strong>: \ud574\ub2f9 \ud568\uc218\uac00 \ud638\ucd9c \ub41c \ud69f\uc218\ub97c \ud655\uc778\ud55c\ub2e4. \uc774 \uacbd\uc6b0 \ud568\uc218\uac00 \uc815\ud655\ud788 1\ubc88 \ud638\ucd9c\ub418\ub294 \uacbd\uc6b0\uac00 \uc544\ub2c8\ub77c\uba74 \ud14c\uc2a4\ud2b8\uac00 \uc2e4\ud328\ud55c\ub2e4.<\/li>\n\n\n\n<li><strong>returning()<\/strong>: \ud574\ub2f9 \ud568\uc218\uac00 \ubc18\ud658\ud560 \uac12\uc744 \uc9c0\uc815\ud55c\ub2e4.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">\uc608\uae08 \ubd80\uc871\uc73c\ub85c \ucd9c\uae08\uc5d0 \uc2e4\ud328\ud558\ub294 \uacbd\uc6b0\ub3c4 \uc791\uc131\ud574 \ubcf4\uc790.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"rust\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">#[test]\nfn test_withdraw_insufficient_funds() {\n    let mut mock_db = MockDatabase::new();\n\n    \/\/ \uc794\uc561\uc774 \ubd80\uc871\ud55c \uc0c1\ud669 \uc5f0\ucd9c (\ud604\uc7ac \uc794\uc561 300000)\n    mock_db.expect_get_user_balance()\n        .with(mockall::predicate::eq(2))\n        .times(1)\n        .returning(|_| Ok(300000));\n\n    \/\/ \uc794\uc561\uc774 \ubd80\uc871\ud558\ubbc0\ub85c update_user_balance\ub294 \ud638\ucd9c\ub418\uc9c0 \uc54a\uc544\uc57c \ud568 (times(0))\n    mock_db.expect_update_user_balance()\n        .times(0);\n\n    let mut service = WalletService::new(mock_db);\n\n    let result = service.withdraw(2, 500000);\n    assert!(result.is_err());\n    assert_eq!(result.unwrap_err(), \"\uc794\uc561\uc774 \ubd80\uc871\ud569\ub2c8\ub2e4.\");\n}\n<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">\uc804\uccb4\ucf54\ub4dc<\/h2>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"rust\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">use mockall::automock;\n\n\/\/ \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc5f0\ub3d9\uc744 \ub2f4\ub2f9\ud558\ub294 Trait\n#[cfg_attr(test, automock)]\npub trait Database {\n    fn get_user_balance(&amp;self, user_id: u64) -> Result&lt;u64, String>;\n    fn update_user_balance(&amp;mut self, user_id: u64, amount: u64) -> Result&lt;(), String>;\n}\n\n\/\/ \ub370\uc774\ud130\ubca0\uc774\uc2a4\ub97c \uc8fc\uc785\ubc1b\uc544 \ube44\uc988\ub2c8\uc2a4 \ub85c\uc9c1\uc744 \uc218\ud589\ud558\ub294 \uc11c\ube44\uc2a4 \uad6c\uc870\uccb4\npub struct WalletService&lt;DB: Database> {\n    db: DB,\n}\n\nimpl&lt;DB: Database> WalletService&lt;DB> {\n    pub fn new(db: DB) -> Self {\n        Self { db }\n    }\n\n    \/\/ \ucd9c\uae08 \ub85c\uc9c1 \uc608\uc2dc\n    pub fn withdraw(&amp;mut self, user_id: u64, amount: u64) -> Result&lt;u64, String> {\n        let current_balance = self.db.get_user_balance(user_id)?;\n\n        if current_balance &lt; amount {\n            return Err(String::from(\"\uc794\uc561\uc774 \ubd80\uc871\ud569\ub2c8\ub2e4.\"));\n        }\n\n        let new_balance = current_balance - amount;\n        self.db.update_user_balance(user_id, new_balance)?;\n\n        Ok(new_balance)\n    }\n}\n\n\/\/ Unittest\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n   #[test]\n    fn test_withdraw_success() {\n        \/\/ mockall\uc774 \uc790\ub3d9 \uc0dd\uc131\ud55c MockDatabase \uad6c\uc870\uccb4 \uc0ac\uc6a9\n        let mut mock_db = MockDatabase::new();\n\n        \/\/ Expectation(\uae30\ub300\uce58) \uc124\uc815\n        \/\/ get_user_balance\ub294 \uc778\uc790\ub85c \uc0ac\uc6a9\uc790 id\uc778 1\uc744 \ubc1b\uc544 \uc794\uc561 1000000\uc744 \ubc18\ud658, 1\ubc88 \ud638\ucd9c\ub418\uc5b4\uc57c \ud568.\n        mock_db.expect_get_user_balance()\n            .with(mockall::predicate::eq(1))\n            .times(1)\n            .returning(|_| Ok(1000000));\n\n        \/\/ update_user_balance\ub294 \uc778\uc790\ub85c \uc0ac\uc6a9\uc790 id '1'\uacfc \uc794\uc561 '500000'\uc744 \ubc1b\uc544 \uc131\uacf5(())\uc744 \ubc18\ud658, 1\ubc88 \ud638\ucd9c\ub418\uc5b4\uc57c \ud568.\n        mock_db.expect_update_user_balance()\n            .with(mockall::predicate::eq(1), mockall::predicate::eq(500000))\n            .times(1)\n            .returning(|_, _| Ok(()));\n\n        \/\/ Database trait \uc0ac\uc6a9\uc790\uc778 WalletService\uc5d0 mock injection\n        let mut service = WalletService::new(mock_db);\n\n        \/\/ \uc2e4\ud589 \ubc0f \uac80\uc99d\n        let result = service.withdraw(1, 500000);\n        assert!(result.is_ok());\n        assert_eq!(result.unwrap(), 500000);\n    }\n\n    #[test]\n    fn test_withdraw_insufficient_funds() {\n        let mut mock_db = MockDatabase::new();\n\n        \/\/ \uc794\uc561\uc774 \ubd80\uc871\ud55c \uc0c1\ud669 \uc5f0\ucd9c (\ud604\uc7ac \uc794\uc561 300000)\n        mock_db.expect_get_user_balance()\n            .with(mockall::predicate::eq(2))\n            .times(1)\n            .returning(|_| Ok(300000));\n\n        \/\/ \uc794\uc561\uc774 \ubd80\uc871\ud558\ubbc0\ub85c update_user_balance\ub294 \ud638\ucd9c\ub418\uc9c0 \uc54a\uc544\uc57c \ud568 (times(0))\n        mock_db.expect_update_user_balance()\n            .times(0);\n\n        let mut service = WalletService::new(mock_db);\n\n        let result = service.withdraw(2, 500000);\n        assert!(result.is_err());\n        assert_eq!(result.unwrap_err(), \"\uc794\uc561\uc774 \ubd80\uc871\ud569\ub2c8\ub2e4.\");\n    }\n}<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">\uacb0\ub860<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\ucf04\ud2b8 \ubca1\uc758 TDD \uc785\ubb38\uc11c\uc778 &#8220;<a href=\"https:\/\/www.nl.go.kr\/seoji\/contents\/S80100000000.do?schM=intgr_detail_view_isbn&amp;page=1&amp;pageUnit=10&amp;schType=simple&amp;schStr=9788991268043&amp;isbn=8991268048&amp;cipId=37637807%2C2053952\" data-type=\"link\" data-id=\"https:\/\/www.nl.go.kr\/seoji\/contents\/S80100000000.do?schM=intgr_detail_view_isbn&amp;page=1&amp;pageUnit=10&amp;schType=simple&amp;schStr=9788991268043&amp;isbn=8991268048&amp;cipId=37637807%2C2053952\">\ud14c\uc2a4\ud2b8 \uc8fc\ub3c4 \uac1c\ubc1c<\/a>&#8220;\uc744 \ub9c9 \uc77d\uace0\ub098\uc11c \uc774\uac83\uc744 \ub0b4 \uac1c\ubc1c \uaddc\uce59\uc5d0 \ub3c4\uc785\ud558\ub824\uace0 \ub178\ub825\ud558\ub358 \ucd08\uae30\uc5d0  <a href=\"https:\/\/google.github.io\/googletest\/gmock_for_dummies.html\" data-type=\"link\" data-id=\"https:\/\/google.github.io\/googletest\/gmock_for_dummies.html\">gmock<\/a>\uc5d0\uc11c \uc81c\uacf5\ud55c\ub2e4\ub294 \ud568\uc218 \ud638\ucd9c \ud69f\uc218\ub97c \uac80\uc0ac\ud558\ub294 \uae30\ub2a5\uc744 \ubd24\uc744 \ub54c\ub294 &#8220;\uc774\uac8c \uc720\uc6a9\ud558\uae30\ub294 \ud560\uae4c?&#8221; \ud558\ub294 \uc758\uad6c\uc2ec\uc744 \uac00\uc84c\ub358 \uc801\uc774 \uc788\uc5c8\ub2e4. \uadf8 \uc774\ud6c4\ub85c \uc774 \uae30\ub2a5\uc774 mock injection\uc744 \ud560 \ub54c caller\uc758 expectation\uc744 \uc810\uac80\ud558\ub294 \ubb34\ucc99 \uc720\uc6a9\ud560 \uae30\ub2a5\uc774\ub77c\ub294 \uac83\uc744 \uae68\ub2eb\uac8c \ub418\uba74\uc11c Java\uc758 unittest\uc5d0\uc11c\ub3c4 mockito\ub97c \uc120\ud638\ud558\uac8c \ub418\uc5c8\ub294\ub370,  Rust\uc5d0\uc11c\ub3c4 \uc774\ub7ec\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud558\ub294 crate\uc774 \uc788\ub2e4\ub294 \uc810\uc774 \ubb34\ucc99 \ub2e4\ud589\uc2a4\ub7fd\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ub77c\uc774\ube0c\ub7ec\ub9ac \ud655\uc7a5 \uae30\ub2a5\uc774 Rust\uc5d0\uc11c \ucc98\uc74c \ub3c4\uc785\ub41c\uac83\ub3c4 \uc720\uc77c\ud55c \uac83\ub3c4 \uc544\ub2c8\uc9c0\ub9cc, \ud604\ub300 \ud504\ub85c\uadf8\ub798\ubc0d \uc5b8\uc5b4\uac00 \uc9c0\ud5a5\ud558\ub294 \ubc14\ub97c \uc801\uadf9\uc801\uc73c\ub85c \ubc1b\uc544\ub4e4\uc774\uba74\uc11c\ub3c4 \uace0\uc131\ub2a5\uc744 \uc720\uc9c0\ud558\ub294 Rust\uac00 \uc810\uc810 \ub354 \ub9e4\ub825\uc788\uac8c \ub290\uaef4\uc9c4\ub2e4.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\ub2e4\ud589\ud788\ub3c4 \uc6b0\ub9ac\ub294 unittest\uc758 \uc720\uc6a9\ud568 \uc798 \uc54c\ub824\uc9c4 \uc2dc\ub300\uc5d0 \uc0b4\uace0 \uc788\uae30\uc5d0 \ub354 \uc774\uc0c1 unittest\ub97c \uc9c0\uc6d0\ud558\ub294 \ud504\ub85c\uadf8\ub798\ubc0d \uc5b8\uc5b4\ub97c \ud2b9\ubcc4\ud558\uac8c \ubc1b\uc544\ub4e4\uc774\uc9c0 \uc54a\ub294\ub2e4. Rust\ub294 \ube44\uad50\uc801 \ucd5c\uc2e0 \uc5b8\uc5b4\uc778 \ub9cc\ud07c \uc774\ub7ec\ud55c \uc694\uad6c\uc0ac\ud56d\ub4e4\uc744 \uc801\uadf9\uc801\uc73c\ub85c \ubc1b\uc544\ub4e4\uc5ec \ubd80\uac00\uc801\uc778 \ud504\ub808\uc784\uc6cc\ud06c\uc758 \ub3c4\uc6c0 \uc5c6\uc774\ub3c4 \uc5b8\uc5b4 \uc790\uccb4\uc5d0\uc11c \uae30\ubcf8\uc801\uc778 unittest\uac00 \uc798 \uc9c0\uc6d0\ub41c\ub2e4. \ub2e4\ub9cc, Rust\ub294 \uc0c1\uc18d\uc744 \uc9c0\uc6d0\ud558\uc9c0 \uc54a\uae30 \ub54c\ubb38\uc5d0 Python, Java, C++ \uac19\uc740 \uac1d\uccb4\uc9c0\ud5a5 \uc5b8\uc5b4\uc5d0\uc11c \uc758\uc874\uc131\uc744 \uaca9\ub9ac \ud560 \ub54c \uc0ac\uc6a9\ub418\ub294 method [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_import_markdown_pro_load_document_selector":0,"_import_markdown_pro_submit_text_textarea":"","_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[5],"tags":[33,475,423,293],"class_list":["post-4528","post","type-post","status-publish","format-standard","hentry","category-programming","tag-database","tag-mocking","tag-rust","tag-unittest"],"jetpack_sharing_enabled":true,"jetpack-related-posts":[{"id":4532,"url":"https:\/\/litcoder.com\/?p=4532","url_meta":{"origin":4528,"position":0},"title":"Rust\uc640 Python unit test\uc758 \uacf5\uc874","author":"litcoder","date":"2026\ub144 7\uc6d4 1\uc77c","format":false,"excerpt":"\uc608\uc804 \uae00\uc5d0\uc11c vscode\uc758 test explorer\uc5d0 Rust\uc758 unittest\uac00 \ubcf4\uc774\ub3c4\ub85d \uc124\uc815\ud558\ub294 \ubc29\ubc95\uc744 \ub2e4\ub8ec \uc801\uc774 \uc788\uc5c8\ub294\ub370, \uc5ec\uae30\uc5d0 Python test case (\uc5ec\uae30\uc11c\ub294 pytest)\ub3c4 \ud568\uaed8 \ud45c\uc2dc\ub418\ub3c4\ub85d \ud558\ub824\uba74 .vscode\/settings.json\uc744 \ud3b8\uc9d1\ud574 \uc8fc\uc5b4\uc57c \ud55c\ub2e4. \ud574\ub2f9 \ud504\ub85c\uc81d\ud2b8\uc758 \uacbd\uc6b0 \uac00\uc0c1\ud658\uacbd\uc744 source root\uc5d0 \ub450\uc9c0 \uc54a\uace0 \uc11c\ube0c \ub514\ub809\ud1a0\ub9ac\uc778 service\/.venv \uc548\uc5d0 \ub123\uc5b4 \ub450\uc5c8\uae30 \ub54c\ubb38\uc5d0 python.defaultInterpreterPath \uac12\uc744 \uc774\uacf3\uc73c\ub85c \uc9c1\uc811 \uc124\uc815\ud574 \uc8fc\uace0 pytest \uc0ac\uc6a9\uc744 \uc704\ud55c\u2026","rel":"","context":"&quot;Tools &amp; Tips&quot;\uc5d0\uc11c","block_context":{"text":"Tools &amp; Tips","link":"https:\/\/litcoder.com\/?cat=6"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/litcoder.com\/wp-content\/uploads\/2026\/06\/vscode_venv_python.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":4281,"url":"https:\/\/litcoder.com\/?p=4281","url_meta":{"origin":4528,"position":1},"title":"Rust: comparison is useless due to type limits","author":"litcoder","date":"2026\ub144 6\uc6d4 17\uc77c","format":false,"excerpt":"\"\ud0c0\uc785 \uc81c\ud55c \ub54c\ubb38\uc5d0 \uc774 \ube44\uad50\uc5f0\uc0b0\uc740 \uc4f8.\ubaa8.\uc5c6.\ub2e4.\" IndexSet\uc774 \ud558\ub098 \uc788\ub2e4\uace0 \ud560 \ub54c, \uadf8 \uc548\uc5d0 \ud558\ub098\ub77c\ub3c4 \uc544\uc774\ud15c\uc774 \uc788\uc73c\uba74 true\ub97c \ubc18\ud658\ud558\uace0 \uc544\ub2c8\uba74 false\ub97c \ubc18\ud658\ud558\ub294 \ub2e4\uc74c\uacfc \uac19\uc740 Rust code\ub97c \uc0dd\uac01\ud574 \ubcf4\uc790. use indexmap::IndexSet; fn has_item(item_set: &IndexSet<String>) -> bool { item_set.iter().count() >= 0 } \uac04\ub2e8\ud558\uac8c unittest\uc5d0 \ub123\uc5b4\uc11c \uc0c8\ub85c \uc0dd\uc131\ud574\uc11c \uc544\ubb34 \uc6d0\uc18c\ub3c4 \uc5c6\ub294 IndexSet\uc744 \ud558\ub098 \ub9cc\ub4e4\uc5b4\uc11c\u2026","rel":"","context":"&quot;Programming&quot;\uc5d0\uc11c","block_context":{"text":"Programming","link":"https:\/\/litcoder.com\/?cat=5"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/litcoder.com\/wp-content\/uploads\/2026\/05\/rust_unused_comparisons.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":4256,"url":"https:\/\/litcoder.com\/?p=4256","url_meta":{"origin":4528,"position":2},"title":"VScode test explorer\uc5d0 Rust \ud14c\uc2a4\ud2b8 \ucf00\uc774\uc2a4 \ud45c\uc2dc","author":"litcoder","date":"2026\ub144 4\uc6d4 1\uc77c","format":false,"excerpt":"rust-analyzer extension\uc744 \uc124\uce58\ud588\ub294\ub370\ub3c4 test explorer\uc5d0\uc11c rust unit test\uac00 \ud45c\uc2dc\ub418\uc9c0 \uc54a\ub294 \uacbd\uc6b0\ub294 \ub2e4\uc74c\uc744 \ud655\uc778\ud574 \ubcf4\uc790. Command palette\uc744 \uc5f4\uc5b4\uc11c open settings\ub97c \uac80\uc0c9\ud55c\ub2e4. \uc67c\ucabd pane\uc5d0\uc11c Extensions -> rust-analyzer\ub97c \uc120\ud0dd\ud558\uace0 Test Explorer \ud56d\ubaa9\uc744 \ucc3e\uc544 \"Show the Test Explorer view.\"\uac00 \uccb4\ud06c\ub418\uc5b4 \uc788\ub294\uc9c0 \ud655\uc778\ud55c\ub2e4. \ud55c\ucc38\uc744 \ucc3e\uc558\ub294\ub370 \uacb0\uad6d\uc740 \uc774\uac8c disabled\ub41c \uac83\uc774 \uc6d0\uc778 \uc774\uc5c8\ub2e4. \uc774 \ud56d\ubaa9\uc744 \uccb4\ud06c\ud558\uace0 \ub098\uba74\u2026","rel":"","context":"&quot;Tools &amp; Tips&quot;\uc5d0\uc11c","block_context":{"text":"Tools &amp; Tips","link":"https:\/\/litcoder.com\/?cat=6"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/litcoder.com\/wp-content\/uploads\/2026\/02\/rust_txset_enabled.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/litcoder.com\/wp-content\/uploads\/2026\/02\/rust_txset_enabled.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/litcoder.com\/wp-content\/uploads\/2026\/02\/rust_txset_enabled.png?resize=525%2C300&ssl=1 1.5x"},"classes":[]},{"id":4374,"url":"https:\/\/litcoder.com\/?p=4374","url_meta":{"origin":4528,"position":3},"title":"Rust \ud504\ub85c\uadf8\ub798\ubc0d\uc5d0\uc11c map() \ud65c\uc6a9","author":"litcoder","date":"2026\ub144 5\uc6d4 13\uc77c","format":false,"excerpt":"Python\uc774 \uadf8\ub7ec\ud558\ub4ef Rust\ub3c4 declarative programming(\uc120\uc5b8\ud615 \ud504\ub85c\uadf8\ub798\ubc0d)\uc744 \uc9c0\uc6d0\ud55c\ub2e4. \uadf8 \uc911 map()\uc740 \uc774\ub7ec\ud55c \ucf54\ub529\uc2a4\ud0c0\uc77c\uc758 \ub300\ud45c\ucc98\ub7fc \uc0ac\uc6a9\ub418\uace0\ub294 \ud558\ub294\ub370, \uc774\uac83\uc744 \uc774\uc6a9\ud558\uba74 \uae38\uace0 \uc7a5\ud669\ud55c \ucf54\ub4dc\ub97c \uac04\uacb0\ud558\uac8c \ub098\ud0c0\ub0bc \uc218 \uc788\ub2e4. \uae30\ubcf8\uc801 \uc0ac\uc6a9\ubc95 1 \ubd80\ud130 10\uae4c\uc9c0 1\uc529 \uc99d\uac00\ud558\ub294 \uac12\uc744 \uac00\uc9c4 i32 \ud615\uc758 10\uce78\uc9dc\ub9ac \ubc30\uc5f4 arr\uc774 \uc788\ub2e4\uace0 \ud560 \ub54c, \uadf8 \uc548\uc5d0 \uc788\ub294 \uac01 \uc6d0\uc18c\ub4e4\uc5d0 2\ub97c \uacf1\ud558\ub294 \ucf54\ub4dc\uc774\ub2e4. \/\/\u2026","rel":"","context":"&quot;Programming&quot;\uc5d0\uc11c","block_context":{"text":"Programming","link":"https:\/\/litcoder.com\/?cat=5"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":4707,"url":"https:\/\/litcoder.com\/?p=4707","url_meta":{"origin":4528,"position":4},"title":"Smoke test\ub97c \uc704\ud55c GitHub Self-hosted Runner \uc124\uc815","author":"litcoder","date":"2026\ub144 9\uc6d4 16\uc77c","format":false,"excerpt":"Unittest\uac00 \uac1c\ubc1c \uacfc\uc815\uc5d0\uc11c \ub17c\ub9ac\ub97c \uc810\uac80\ud558\ub294\ub370 \uc720\uc6a9\ud558\uae30\ub294 \ud558\uc9c0\ub9cc \uc774\uc138\uc0c1\uc5d0\ub294 integration test\uac00 \ub2f4\ub2f9\ud574\uc57c \ud558\ub294 \ubd80\ubd84\ub3c4 \uc5c4\uc5f0\ud788 \uc874\uc7ac\ud55c\ub2e4. \uac01\uac01\uc758 \ucef4\ud3ec\ub10c\ud2b8\ub4e4\uc774 \uc798 \uc791\uc131\ub418\uc5c8\ub2e4 \ud560\uc9c0\ub77c\ub3c4 \uc774\uac83\uc744 \ud1b5\ud569\ud588\uc744 \ub54c\uc758 \ub3d9\uc791\uc744 \ubcf4\uc7a5\ud558\ub294 \uac83\uc740 \ub610 \ub2e4\ub978 \uc774\uc57c\uae30 \uc774\uae30 \ub54c\ubb38\uc774\ub2e4. \uc774 \ubd80\ubd84\uc744 \ucee4\ubc84\ud558\uae30 \uc704\ud55c \ubaa9\uc801\uc73c\ub85c \uac00\uc0c1\uc758 \ub370\uc774\ud130\ub97c \uc0dd\uc131\ud558\uace0 \ud504\ub85c\uadf8\ub7a8\uc758 \ucc98\uc74c \uc2dc\uc791 \ubd80\ubd84\ubd80\ud130 \ub9c8\uc9c0\ub9c9 \ucd9c\ub825 \ubd80\ubd84\uae4c\uc9c0(E2E) \uc810\uac80\ud558\ub294 \uc2a4\ud06c\ub9bd\ud2b8\ub97c \ub9cc\ub4e4\uc5b4 \ub450\uc5c8\ub2e4.\u2026","rel":"","context":"&quot;Linux&quot;\uc5d0\uc11c","block_context":{"text":"Linux","link":"https:\/\/litcoder.com\/?cat=4"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/litcoder.com\/wp-content\/uploads\/2026\/08\/github_vm_no_space_error.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/litcoder.com\/wp-content\/uploads\/2026\/08\/github_vm_no_space_error.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/litcoder.com\/wp-content\/uploads\/2026\/08\/github_vm_no_space_error.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/litcoder.com\/wp-content\/uploads\/2026\/08\/github_vm_no_space_error.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/litcoder.com\/wp-content\/uploads\/2026\/08\/github_vm_no_space_error.png?resize=1050%2C600&ssl=1 3x, https:\/\/i0.wp.com\/litcoder.com\/wp-content\/uploads\/2026\/08\/github_vm_no_space_error.png?resize=1400%2C800&ssl=1 4x"},"classes":[]},{"id":4654,"url":"https:\/\/litcoder.com\/?p=4654","url_meta":{"origin":4528,"position":5},"title":"PyO3\ub85c Rust code\uc5d0\uc11c Python module \uc0ac\uc6a9\ud558\uae30","author":"litcoder","date":"2026\ub144 8\uc6d4 19\uc77c","format":false,"excerpt":"PyO3\ub97c \uc774\uc6a9\ud558\uba74 Rust\uc5d0\uc11c Python\uc744 \ud638\ucd9c\ud558\uac70\ub098 \ubc18\ub300\ub85c Python\uc5d0\uc11c Rust\ub97c \ud638\ucd9c\ud558\ub294 \ubc14\uc778\ub529\uc744 \uad6c\ud604\ud560 \uc218 \uc788\ub2e4. \uc774 \ud3ec\uc2a4\ud305\uc5d0\uc11c\ub294 \uc608\uc804\uc5d0 \ud574\ubd24\ub358 Datumaro\ub85c \ub370\uc774\ud130\uc14b\uc744 detect\ud558\ub294 Python\ud568\uc218\ub97c Rust\ub85c \ud638\ucd9c\ud558\ub294 \uc608\uc81c\ub97c \uad6c\ud604\ud574 \ubcf8\ub2e4. Python \uc758\uc874\uc124 \uc124\uce58 Python \uad00\ub828\ud55c \uc758\uc874\uc131\uc740 \uc608\uc804\uacfc \uac19\uc774 Datumaro\ub97c \uc0ac\uc6a9\ud558\ub294\ub370 \ud544\uc694\ud55c \uac83\ub4e4\uc744 \uc124\uce58\ud574 \uc900\ub2e4. pip install 'datumaro[tf,tfds]' \\ tensorboardX \\ tensorflow-dataset \\ importlib_resources \\\u2026","rel":"","context":"&quot;Programming&quot;\uc5d0\uc11c","block_context":{"text":"Programming","link":"https:\/\/litcoder.com\/?cat=5"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/litcoder.com\/wp-content\/uploads\/2026\/07\/sc_dsdetect_rust.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/litcoder.com\/wp-content\/uploads\/2026\/07\/sc_dsdetect_rust.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/litcoder.com\/wp-content\/uploads\/2026\/07\/sc_dsdetect_rust.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/litcoder.com\/wp-content\/uploads\/2026\/07\/sc_dsdetect_rust.png?resize=700%2C400&ssl=1 2x"},"classes":[]}],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/litcoder.com\/index.php?rest_route=\/wp\/v2\/posts\/4528","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/litcoder.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/litcoder.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/litcoder.com\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/litcoder.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=4528"}],"version-history":[{"count":20,"href":"https:\/\/litcoder.com\/index.php?rest_route=\/wp\/v2\/posts\/4528\/revisions"}],"predecessor-version":[{"id":4706,"href":"https:\/\/litcoder.com\/index.php?rest_route=\/wp\/v2\/posts\/4528\/revisions\/4706"}],"wp:attachment":[{"href":"https:\/\/litcoder.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4528"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/litcoder.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=4528"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/litcoder.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=4528"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}