using Infrastructure.StockData; namespace Application.Tests; [TestClass] public sealed class KoreaEximExchangeParserTests { [TestMethod] public void Parse_UsdAndJpy100_MapsUnitNameRateAndTtbTts() { // 수출입은행 AP01 응답 골격 — 최상위 배열, 값은 전부 문자열, 천단위 콤마 포함. JPY(100)/IDR(100) 등 "(100)" 단위 원문 보존 const string json = """ [ {"result":1,"cur_unit":"USD","cur_nm":"미국 달러","ttb":"1,382.10","tts":"1,410.30","deal_bas_r":"1,396.20","bkpr":"1,396","kftc_deal_bas_r":"1,396.20"}, {"result":1,"cur_unit":"JPY(100)","cur_nm":"일본 옌","ttb":"905.11","tts":"923.55","deal_bas_r":"914.33","bkpr":"914","kftc_deal_bas_r":"914.33"} ] """; var rows = KoreaEximExchangeParser.Parse(json); Assert.AreEqual(2, rows.Count); var usd = rows[0]; Assert.AreEqual("USD", usd.CurrencyUnit); Assert.AreEqual("미국 달러", usd.CurrencyName); Assert.AreEqual(1396.20m, usd.DealBasRate, "deal_bas_r 천단위 콤마 제거"); Assert.AreEqual(1382.10m, usd.Ttb); Assert.AreEqual(1410.30m, usd.Tts); var jpy = rows[1]; Assert.AreEqual("JPY(100)", jpy.CurrencyUnit, "\"(100)\" 단위 표기 원문 보존"); Assert.AreEqual(914.33m, jpy.DealBasRate); } [TestMethod] public void Parse_RowWithFailedResultCode_IsSkipped() { // result != 1 인 행은 skip (여기선 3=인증코드 오류). 성공(1) 행만 남는다. const string json = """ [ {"result":3,"cur_unit":"USD","cur_nm":"미국 달러","deal_bas_r":"1,396.20"}, {"result":1,"cur_unit":"EUR","cur_nm":"유로","ttb":"","tts":"","deal_bas_r":"1,502.44"} ] """; var rows = KoreaEximExchangeParser.Parse(json); Assert.AreEqual(1, rows.Count, "result=3 행은 제외"); Assert.AreEqual("EUR", rows[0].CurrencyUnit); Assert.AreEqual(1502.44m, rows[0].DealBasRate); Assert.IsNull(rows[0].Ttb, "빈 ttb 는 null"); Assert.IsNull(rows[0].Tts, "빈 tts 는 null"); } [TestMethod] public void Parse_MissingDealBasRate_RowIsSkipped() { // deal_bas_r 파싱 실패(빈값) 행은 매매기준율이 없으므로 skip const string json = """ [ {"result":1,"cur_unit":"XDR","cur_nm":"SDR","ttb":"","tts":"","deal_bas_r":""} ] """; Assert.AreEqual(0, KoreaEximExchangeParser.Parse(json).Count); } [TestMethod] public void Parse_EmptyArrayOrNonArrayOrBlank_ReturnsEmpty() { // koreaexim quirk: 주말/공휴일·오전 이전엔 빈 배열([]) → 0건 Assert.AreEqual(0, KoreaEximExchangeParser.Parse("[]").Count); // 오류/빈 응답도 예외 없이 0건 Assert.AreEqual(0, KoreaEximExchangeParser.Parse("").Count); Assert.AreEqual(0, KoreaEximExchangeParser.Parse("{\"result\":4}").Count, "배열이 아니면 0건"); } }