Skip to main content
Glama
gqy20

Europe PMC Literature Search MCP Server

test_crossref_service.py9.31 kB
""" CrossRef 服务单元测试 """ from unittest.mock import Mock from unittest.mock import patch import pytest from src.crossref_service import CrossRefService class TestCrossRefService: """CrossRef 服务测试类""" @pytest.fixture def service(self, logger): """创建 CrossRef 服务实例""" return CrossRefService(logger) def test_init(self, service): """测试服务初始化""" assert service.base_url == "https://api.crossref.org" assert service.api_client is not None assert hasattr(service, "search_works") assert hasattr(service, "get_work_by_doi") assert hasattr(service, "get_references") @patch("src.crossref_service.get_api_client") def test_search_works_success(self, mock_get_client, service): """测试成功搜索""" # 模拟 API 客户端 mock_client = Mock() mock_client.get.return_value = { "success": True, "data": { "message": { "items": [ { "title": ["Test Article"], "author": [{"name": "Test Author"}], "DOI": "10.1234/test", } ], "total-results": 1, } }, } mock_get_client.return_value = mock_client # 重新创建服务以使用 mock service = CrossRefService(None) result = service.search_works("test query", max_results=10) assert result["success"] is True assert len(result["articles"]) == 1 assert result["total_count"] == 1 assert result["source"] == "crossref" @patch("src.crossref_service.get_api_client") def test_search_works_api_failure(self, mock_get_client, service): """测试 API 调用失败""" mock_client = Mock() mock_client.get.return_value = {"success": False, "error": "API Error"} mock_get_client.return_value = mock_client service = CrossRefService(None) result = service.search_works("test query", max_results=10) assert result["success"] is False assert result["error"] == "API调用失败" assert len(result["articles"]) == 0 assert result["source"] == "crossref" @patch("src.crossref_service.get_api_client") def test_search_works_exception(self, mock_get_client, service): """测试搜索过程中的异常""" mock_client = Mock() mock_client.get.side_effect = Exception("Network Error") mock_get_client.return_value = mock_client service = CrossRefService(None) result = service.search_works("test query", max_results=10) assert result["success"] is False assert "Network Error" in result["error"] assert len(result["articles"]) == 0 def test_format_single_article_complete(self, service): """测试格式化完整文章数据""" item = { "title": ["Test Article Title"], "author": [{"given": "John", "family": "Doe"}, {"name": "Jane Smith"}], "DOI": "10.1234/test.2023", "short-container-title": ["Test Journal"], "created": {"date-time": "2023-01-15T10:30:00Z"}, } result = service._format_single_article(item) assert result["title"] == "Test Article Title" assert result["authors"] == ["John Doe", "Jane Smith"] assert result["doi"] == "10.1234/test.2023" assert result["journal"] == "Test Journal" assert result["publication_date"] == "2023-01-15T10:30:00Z" assert result["source"] == "crossref" def test_format_single_article_minimal(self, service): """测试格式化最少的文章数据""" item = {} result = service._format_single_article(item) assert result["title"] == "" assert result["authors"] == [] assert result["doi"] is None assert result["journal"] == "" assert result["publication_date"] == "" assert result["source"] == "crossref" def test_format_single_article_with_none_values(self, service): """测试格式化包含 None 值的文章数据""" item = { "title": None, "author": None, "DOI": None, "short-container-title": None, "created": None, } result = service._format_single_article(item) assert result["title"] == "" assert result["authors"] == [] assert result["doi"] is None assert result["journal"] == "" assert result["publication_date"] == "" assert result["source"] == "crossref" def test_format_single_article_with_none_author(self, service): """测试格式化包含 None 作者的文章数据""" item = { "title": ["Test Article"], "author": [{"given": "John", "family": "Doe"}, None, {"name": "Jane Smith"}], "DOI": "10.1234/test", } result = service._format_single_article(item) assert result["title"] == "Test Article" assert result["authors"] == ["John Doe", "Jane Smith"] assert result["doi"] == "10.1234/test" def test_extract_title(self, service): """测试标题提取""" # 正常情况 assert service._extract_title(["Title 1", "Title 2"]) == "Title 1" # 空列表 assert service._extract_title([]) == "" # None 值(通过 .get('title') or [] 处理) assert service._extract_title(None) == "" def test_extract_authors(self, service): """测试作者提取""" # 正常情况 authors = [{"given": "John", "family": "Doe"}, {"name": "Jane Smith"}] result = service._extract_authors(authors) assert result == ["John Doe", "Jane Smith"] # 空列表 assert service._extract_authors([]) == [] # 包含 None 值 authors_with_none = [{"given": "John", "family": "Doe"}, None, {"name": "Jane Smith"}] result = service._extract_authors(authors_with_none) assert result == ["John Doe", "Jane Smith"] def test_format_references(self, service): """测试参考文献格式化""" references = [ { "DOI": "10.1234/ref1", "title": ["Reference 1"], "author": [{"name": "Ref Author"}], "created": {"date-parts": [[2023]]}, }, {"DOI": None, "title": None, "author": None, "created": None}, ] result = service._format_references(references) assert len(result) == 2 assert result[0]["doi"] == "10.1234/ref1" assert result[0]["title"] == "Reference 1" assert result[0]["authors"] == ["Ref Author"] assert result[0]["year"] == 2023 assert result[1]["doi"] is None assert result[1]["title"] == "" assert result[1]["authors"] == [] assert result[1]["year"] is None @patch("src.crossref_service.get_api_client") def test_get_work_by_doi_success(self, mock_get_client): """测试通过 DOI 获取文章成功""" mock_client = Mock() mock_client.get.return_value = { "success": True, "data": { "message": { "title": ["Test Article"], "author": [{"name": "Test Author"}], "DOI": "10.1234/test", } }, } mock_get_client.return_value = mock_client service = CrossRefService(None) result = service.get_work_by_doi("10.1234/test") assert result["success"] is True assert result["article"]["title"] == "Test Article" assert result["source"] == "crossref" @patch("src.crossref_service.get_api_client") def test_get_work_by_doi_not_found(self, mock_get_client): """测试通过 DOI 获取文章未找到""" mock_client = Mock() mock_client.get.return_value = {"success": True, "data": {"message": {"items": []}}} mock_get_client.return_value = mock_client service = CrossRefService(None) result = service.get_work_by_doi("10.9999/nonexistent") assert result["success"] is False assert result["article"] is None assert result["source"] == "crossref" def test_lru_cache_behavior(self, service): """测试 LRU 缓存行为""" # 这个测试检查缓存装饰器是否正常工作 # 由于我们使用了 @lru_cache,相同的调用应该使用缓存 with patch.object(service, "api_client") as mock_client: mock_client.get.return_value = { "success": True, "data": {"message": {"items": [], "total-results": 0}}, } # 第一次调用 result1 = service.search_works("test", max_results=5) # 第二次调用应该使用缓存 result2 = service.search_works("test", max_results=5) # 验证只调用了一次 API assert mock_client.get.call_count == 1 assert result1 == result2

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/gqy20/article-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server