Files
myquant/djapi/api/report/tests.py
T
Simon 6acf938caf docs: 文档重构 — 清理 AI agent 残留,整合 docs/ 目录结构
- 删除 11 个残留文件: continuation.md, init_plan.md, reasonix.toml, djapi/continuation.md, djapi/.serena/, djapi/.claude/, djapi/.mcp.json, .claude/skills/, docs/usage.html, docs/db_schema.md, docs/report_db_design.md
- 7 个 CLAUDE-*.md 移入 docs/ 并重命名去 CLAUDE- 前缀
- 新增 4 个文档: architecture.md, development.md, api.md, deployment.md
- 重写 usage.md, README.md
- 修复所有过时引用和交叉链接
2026-08-22 11:56:40 +08:00

161 lines
6.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
日报查询 API 测试(GET /api/news/reports/ 与 /api/news/events/)。
通过 mock 数据库查询层(api.report.query.*),只验证视图层
参数解析 / 默认窗口 / 响应结构 / 错误处理,不依赖真实 MySQL。
"""
from datetime import timedelta
from unittest.mock import patch
from django.test import TestCase
from django.utils import timezone
from rest_framework.test import APIClient
class NewsReportsAPITest(TestCase):
"""GET /api/news/reports/ 日报查询"""
def setUp(self):
self.client = APIClient()
self.url = '/api/news/reports/'
@patch('api.report.query.fetch_reports', return_value=[])
def test_default_window_last_24h(self, mock_fetch):
resp = self.client.get(self.url)
self.assertEqual(resp.status_code, 200)
self.assertEqual(resp.json(), [])
kwargs = mock_fetch.call_args.kwargs
now = timezone.now()
self.assertEqual(kwargs['start_date'], (now - timedelta(hours=24)).date())
self.assertEqual(kwargs['end_date'], now.date())
self.assertIsNone(kwargs['report_type'])
self.assertIsNone(kwargs['report_id'])
@patch('api.report.query.fetch_reports',
return_value=[{'id': 1, 'report_date': '2026-08-01', 'report_type': 'finance'}])
def test_report_type_and_date_range(self, mock_fetch):
resp = self.client.get(self.url, {
'report_type': 'finance',
'start_date': '2026-07-01',
'end_date': '2026-08-03',
})
self.assertEqual(resp.status_code, 200)
self.assertEqual(len(resp.json()), 1)
kwargs = mock_fetch.call_args.kwargs
self.assertEqual(kwargs['report_type'], 'finance')
self.assertEqual(str(kwargs['start_date']), '2026-07-01')
self.assertEqual(str(kwargs['end_date']), '2026-08-03')
@patch('api.report.query.fetch_reports')
def test_detail_by_id(self, mock_fetch):
mock_fetch.return_value = {
'id': 10, 'report_date': '2026-08-03', 'report_type': 'finance',
'events': [{'id': 1, 'title': '事件一'}],
}
resp = self.client.get(self.url, {'id': '10'})
self.assertEqual(resp.status_code, 200)
self.assertEqual(resp.json()['id'], 10)
self.assertEqual(mock_fetch.call_args.kwargs['report_id'], 10)
@patch('api.report.query.fetch_reports', return_value=None)
def test_detail_not_found(self, mock_fetch):
resp = self.client.get(self.url, {'id': '99999'})
self.assertEqual(resp.status_code, 404)
self.assertIn('error', resp.json())
def test_invalid_report_type(self):
resp = self.client.get(self.url, {'report_type': 'xxx'})
self.assertEqual(resp.status_code, 400)
def test_invalid_date_format(self):
resp = self.client.get(self.url, {'start_date': '2026/07/01'})
self.assertEqual(resp.status_code, 400)
def test_invalid_id(self):
resp = self.client.get(self.url, {'id': 'abc'})
self.assertEqual(resp.status_code, 400)
def test_non_positive_id(self):
resp = self.client.get(self.url, {'id': '0'})
self.assertEqual(resp.status_code, 400)
@patch('api.report.query.fetch_reports', side_effect=RuntimeError('db down'))
def test_query_error_500(self, mock_fetch):
resp = self.client.get(self.url)
self.assertEqual(resp.status_code, 500)
self.assertIn('error', resp.json())
class NewsEventsAPITest(TestCase):
"""GET /api/news/events/ 重要事件聚合"""
def setUp(self):
self.client = APIClient()
self.url = '/api/news/events/'
@patch('api.report.query.fetch_important_events', return_value=[])
def test_defaults(self, mock_fetch):
resp = self.client.get(self.url)
self.assertEqual(resp.status_code, 200)
self.assertEqual(resp.json(), [])
kwargs = mock_fetch.call_args.kwargs
self.assertEqual(kwargs['days'], 7)
self.assertEqual(kwargs['importance'], 4)
self.assertEqual(kwargs['limit'], 100)
self.assertIsNone(kwargs['report_type'])
self.assertIsNone(kwargs['section'])
@patch('api.report.query.fetch_important_events',
return_value=[{'id': 1, 'title': '重要事件', 'importance': 5}])
def test_filters(self, mock_fetch):
resp = self.client.get(self.url, {
'days': '3', 'importance': '5',
'report_type': 'intl', 'section': 'intl', 'limit': '10',
})
self.assertEqual(resp.status_code, 200)
self.assertEqual(len(resp.json()), 1)
kwargs = mock_fetch.call_args.kwargs
self.assertEqual(kwargs['days'], 3)
self.assertEqual(kwargs['importance'], 5)
self.assertEqual(kwargs['limit'], 10)
self.assertEqual(kwargs['report_type'], 'intl')
self.assertEqual(kwargs['section'], 'intl')
@patch('api.report.query.fetch_important_events',
return_value=[{'id': 1, 'title': 'x', 'source': 'yicai',
'sources': ['yicai', 'stcn']}])
def test_sources_field_passthrough(self, mock_fetch):
"""事件聚合响应原样透传 sources(JSON 数组)"""
resp = self.client.get(self.url)
self.assertEqual(resp.status_code, 200)
body = resp.json()
self.assertEqual(body[0]['sources'], ['yicai', 'stcn'])
self.assertEqual(body[0]['source'], 'yicai')
def test_invalid_days(self):
resp = self.client.get(self.url, {'days': 'abc'})
self.assertEqual(resp.status_code, 400)
def test_days_out_of_range(self):
resp = self.client.get(self.url, {'days': '0'})
self.assertEqual(resp.status_code, 400)
def test_invalid_importance(self):
resp = self.client.get(self.url, {'importance': '9'})
self.assertEqual(resp.status_code, 400)
def test_invalid_section(self):
resp = self.client.get(self.url, {'section': 'foo'})
self.assertEqual(resp.status_code, 400)
def test_invalid_report_type(self):
resp = self.client.get(self.url, {'report_type': 'xxx'})
self.assertEqual(resp.status_code, 400)
@patch('api.report.query.fetch_important_events', side_effect=RuntimeError('db down'))
def test_query_error_500(self, mock_fetch):
resp = self.client.get(self.url)
self.assertEqual(resp.status_code, 500)
self.assertIn('error', resp.json())