DartDisclosureParserTests.cs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. using Infrastructure.StockData;
  2. namespace Application.Tests;
  3. [TestClass]
  4. public sealed class DartDisclosureParserTests
  5. {
  6. [TestMethod]
  7. public void Parse_Success_MapsAllFieldsAndMeta()
  8. {
  9. // OpenDART list.json 실검증 shape — status "000", 상장(stock_code 6자리) 항목
  10. const string json = """
  11. {"status":"000","message":"정상","page_no":1,"page_count":100,"total_count":1178,"total_page":12,
  12. "list":[
  13. {"corp_code":"00126380","corp_name":"삼성전자","stock_code":"005930","corp_cls":"Y","report_nm":"주요사항보고서(자기주식취득결정)","rcept_no":"20250103000123","flr_nm":"삼성전자","rcept_dt":"20250103","rm":""}
  14. ]}
  15. """;
  16. var result = DartDisclosureParser.Parse(json);
  17. Assert.AreEqual("000", result.Status);
  18. Assert.AreEqual("정상", result.Message);
  19. Assert.AreEqual(1, result.PageNo);
  20. Assert.AreEqual(12, result.TotalPage);
  21. Assert.AreEqual(1178, result.TotalCount);
  22. Assert.AreEqual(1, result.Rows.Count);
  23. var d = result.Rows[0];
  24. Assert.AreEqual("20250103000123", d.RceptNo, "접수번호 14자리");
  25. Assert.AreEqual("00126380", d.CorpCode, "고유번호 8자리");
  26. Assert.AreEqual("삼성전자", d.CorpName);
  27. Assert.AreEqual("005930", d.StockCode, "상장 종목코드 6자리");
  28. Assert.AreEqual("Y", d.CorpCls, "유가증권시장");
  29. Assert.AreEqual("주요사항보고서(자기주식취득결정)", d.ReportNm);
  30. Assert.AreEqual("삼성전자", d.FlrNm);
  31. Assert.AreEqual(new DateOnly(2025, 1, 3), d.RceptDt, "rcept_dt YYYYMMDD → DateOnly");
  32. Assert.IsNull(d.Rm, "빈 rm 은 null");
  33. }
  34. [TestMethod]
  35. public void Parse_EmptyStockCode_BecomesNull()
  36. {
  37. // 비상장(자산운용 등) — stock_code "" → null, corp_cls "E"(기타), rm "정"(정정)
  38. const string json = """
  39. {"status":"000","message":"정상","page_no":1,"page_count":100,"total_count":1,"total_page":1,
  40. "list":[
  41. {"corp_code":"00380942","corp_name":"카디안자산운용","stock_code":"","corp_cls":"E","report_nm":"[기재정정]일괄신고서(집합투자증권-신탁형)","rcept_no":"20250103000294","flr_nm":"카디안자산운용","rcept_dt":"20250103","rm":"정"}
  42. ]}
  43. """;
  44. var result = DartDisclosureParser.Parse(json);
  45. Assert.AreEqual(1, result.Rows.Count);
  46. var d = result.Rows[0];
  47. Assert.IsNull(d.StockCode, "비상장 stock_code \"\" 는 null");
  48. Assert.AreEqual("E", d.CorpCls);
  49. Assert.AreEqual("정", d.Rm, "비고(rm) 유지");
  50. }
  51. [TestMethod]
  52. public void Parse_Status013_NoData_ReturnsEmptyRows()
  53. {
  54. // 013 = 조회된 데이터 없음 — list 노드 없이 status/message 만
  55. const string json = """
  56. {"status":"013","message":"조회된 데이터가 없습니다."}
  57. """;
  58. var result = DartDisclosureParser.Parse(json);
  59. Assert.AreEqual("013", result.Status);
  60. Assert.AreEqual(0, result.Rows.Count, "013 은 빈 목록");
  61. }
  62. [TestMethod]
  63. public void Parse_KeyError_Status020_ReturnsEmptyRows()
  64. {
  65. // 020 = 등록되지 않은 키 등 오류 — status != "000" 이면 rows 비움
  66. const string json = """
  67. {"status":"020","message":"등록되지 않은 키입니다."}
  68. """;
  69. var result = DartDisclosureParser.Parse(json);
  70. Assert.AreEqual("020", result.Status);
  71. Assert.AreEqual(0, result.Rows.Count);
  72. }
  73. [TestMethod]
  74. public void Parse_MultipleRows_DateParsing()
  75. {
  76. // 여러 행 — 각기 다른 접수일 파싱 확인
  77. const string json = """
  78. {"status":"000","message":"정상","page_no":1,"page_count":100,"total_count":2,"total_page":1,
  79. "list":[
  80. {"corp_code":"00111111","corp_name":"에이","stock_code":"111111","corp_cls":"K","report_nm":"분기보고서","rcept_no":"20250102000001","flr_nm":"에이","rcept_dt":"20250102","rm":""},
  81. {"corp_code":"00222222","corp_name":"비","stock_code":"222222","corp_cls":"N","report_nm":"사업보고서","rcept_no":"20250103000002","flr_nm":"비","rcept_dt":"20250103","rm":"첨부추가"}
  82. ]}
  83. """;
  84. var result = DartDisclosureParser.Parse(json);
  85. Assert.AreEqual(2, result.Rows.Count);
  86. Assert.AreEqual(new DateOnly(2025, 1, 2), result.Rows[0].RceptDt);
  87. Assert.AreEqual("K", result.Rows[0].CorpCls, "코스닥");
  88. Assert.AreEqual(new DateOnly(2025, 1, 3), result.Rows[1].RceptDt);
  89. Assert.AreEqual("N", result.Rows[1].CorpCls, "코넥스");
  90. Assert.AreEqual("첨부추가", result.Rows[1].Rm);
  91. }
  92. [TestMethod]
  93. public void Parse_MissingRequiredField_RowSkipped()
  94. {
  95. // 필수(rcept_no/corp_code/report_nm/rcept_dt) 결측 행은 건너뜀 — 방어
  96. const string json = """
  97. {"status":"000","message":"정상","page_no":1,"page_count":100,"total_count":2,"total_page":1,
  98. "list":[
  99. {"corp_code":"00333333","corp_name":"씨","stock_code":"333333","corp_cls":"Y","report_nm":"","rcept_no":"20250103000003","flr_nm":"씨","rcept_dt":"20250103","rm":""},
  100. {"corp_code":"00444444","corp_name":"디","stock_code":"444444","corp_cls":"Y","report_nm":"정기보고서","rcept_no":"20250103000004","flr_nm":"디","rcept_dt":"20250103","rm":""}
  101. ]}
  102. """;
  103. var result = DartDisclosureParser.Parse(json);
  104. Assert.AreEqual(1, result.Rows.Count, "report_nm 빈 행은 skip");
  105. Assert.AreEqual("20250103000004", result.Rows[0].RceptNo);
  106. }
  107. }