KrxEsgSecurityParserTests.cs 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. using Infrastructure.StockData;
  2. namespace Application.Tests;
  3. [TestClass]
  4. public sealed class KrxEsgSecurityParserTests
  5. {
  6. [TestMethod]
  7. public void ParseDaily_MapsFields_FromSampleJson()
  8. {
  9. // KRX OpenAPI(esg/esg_etp_info) 실검증 샘플 — ISU_CD 없음(종목명만), FLUC_RT 는 소수 % 그대로(".06"/"-.43" 형태 포함), 천단위 콤마 방어
  10. const string json = """
  11. {"OutBlock_1":[
  12. {"BAS_DD":"20250102","ISU_ABBRV":"HANARO 탄소효율그린뉴딜","TDD_CLSPRC":"7,880","CMPPREVDD_PRC":"5","FLUC_RT":".06","LIST_SHRS":"900,000","ACC_TRDVOL":"2,723","ACC_TRDVAL":"21,348,240"},
  13. {"BAS_DD":"20250102","ISU_ABBRV":"KODEX 200ESG","TDD_CLSPRC":"12860","CMPPREVDD_PRC":"-55","FLUC_RT":"-.43","LIST_SHRS":"2700000","ACC_TRDVOL":"5276","ACC_TRDVAL":"67842290"}
  14. ]}
  15. """;
  16. var rows = KrxEsgSecurityParser.ParseDaily(json);
  17. Assert.AreEqual(2, rows.Count);
  18. var a = rows[0];
  19. Assert.AreEqual("HANARO 탄소효율그린뉴딜", a.Name);
  20. Assert.AreEqual(new DateOnly(2025, 1, 2), a.TradeDate);
  21. Assert.AreEqual(7880m, a.Close, "종가 콤마 제거");
  22. Assert.AreEqual(5m, a.ChangeAmount);
  23. Assert.AreEqual(0.06m, a.ChangeRate, "FLUC_RT '.06' → 0.06 소수 % 그대로 (Bp 아님)");
  24. Assert.AreEqual(900000L, a.ListedShares, "상장좌수 콤마 제거");
  25. Assert.AreEqual(2723L, a.Volume);
  26. Assert.AreEqual(21348240L, a.TradeValue);
  27. var b = rows[1];
  28. Assert.AreEqual("KODEX 200ESG", b.Name);
  29. Assert.AreEqual(12860m, b.Close);
  30. Assert.AreEqual(-55m, b.ChangeAmount);
  31. Assert.AreEqual(-0.43m, b.ChangeRate, "FLUC_RT '-.43' → -0.43");
  32. }
  33. [TestMethod]
  34. public void ParseDaily_ZeroChangeAndVolume_AreZero()
  35. {
  36. // 무거래일 종목 — CMPPREVDD_PRC/FLUC_RT/ACC_TRDVOL/ACC_TRDVAL 모두 "0"
  37. const string json = """
  38. {"OutBlock_1":[
  39. {"BAS_DD":"20250102","ISU_ABBRV":"FOCUS ESG리더스","TDD_CLSPRC":"10385","CMPPREVDD_PRC":"0","FLUC_RT":"0","LIST_SHRS":"450000","ACC_TRDVOL":"0","ACC_TRDVAL":"0"}
  40. ]}
  41. """;
  42. var rows = KrxEsgSecurityParser.ParseDaily(json);
  43. Assert.AreEqual(1, rows.Count);
  44. var r = rows[0];
  45. Assert.AreEqual(10385m, r.Close);
  46. Assert.AreEqual(0m, r.ChangeAmount);
  47. Assert.AreEqual(0m, r.ChangeRate);
  48. Assert.AreEqual(0L, r.Volume);
  49. Assert.AreEqual(0L, r.TradeValue);
  50. }
  51. [TestMethod]
  52. public void ParseDaily_EmptyOrMissingBlock_ReturnsEmpty()
  53. {
  54. // basDd 미반영 — OutBlock_1 빈 배열
  55. Assert.AreEqual(0, KrxEsgSecurityParser.ParseDaily("""{"OutBlock_1":[]}""").Count);
  56. // 인증 실패 등 OutBlock_1 노드 자체가 없는 응답도 안전하게 0건
  57. Assert.AreEqual(0, KrxEsgSecurityParser.ParseDaily("""{"respMsg":"Unauthorized API Call","respCode":"401"}""").Count);
  58. }
  59. }