| """Unit tests for Europe PMC tool.""" |
|
|
| from unittest.mock import AsyncMock, MagicMock, patch |
|
|
| import pytest |
|
|
| from src.tools.europepmc import EuropePMCTool |
| from src.utils.models import Evidence |
|
|
|
|
| @pytest.mark.unit |
| class TestEuropePMCTool: |
| """Tests for EuropePMCTool.""" |
|
|
| @pytest.fixture |
| def tool(self) -> EuropePMCTool: |
| return EuropePMCTool() |
|
|
| def test_tool_name(self, tool: EuropePMCTool) -> None: |
| assert tool.name == "europepmc" |
|
|
| @pytest.mark.asyncio |
| async def test_search_returns_evidence(self, tool: EuropePMCTool) -> None: |
| """Test that search returns Evidence objects.""" |
| mock_response = { |
| "resultList": { |
| "result": [ |
| { |
| "id": "12345", |
| "title": "Long COVID Treatment Study", |
| "abstractText": "This study examines treatments for Long COVID.", |
| "doi": "10.1234/test", |
| "pubYear": "2024", |
| "source": "MED", |
| "pubTypeList": {"pubType": ["research-article"]}, |
| } |
| ] |
| } |
| } |
|
|
| with patch("httpx.AsyncClient") as mock_client: |
| mock_instance = AsyncMock() |
| mock_client.return_value.__aenter__.return_value = mock_instance |
|
|
| |
| mock_resp = MagicMock() |
| mock_resp.json.return_value = mock_response |
| mock_resp.raise_for_status.return_value = None |
|
|
| mock_instance.get.return_value = mock_resp |
|
|
| results = await tool.search("long covid treatment", max_results=5) |
|
|
| assert len(results) == 1 |
| assert isinstance(results[0], Evidence) |
| assert "Long COVID Treatment Study" in results[0].citation.title |
|
|
| @pytest.mark.asyncio |
| async def test_search_marks_preprints(self, tool: EuropePMCTool) -> None: |
| """Test that preprints are marked correctly.""" |
| mock_response = { |
| "resultList": { |
| "result": [ |
| { |
| "id": "PPR12345", |
| "title": "Preprint Study", |
| "abstractText": "Abstract text", |
| "doi": "10.1234/preprint", |
| "pubYear": "2024", |
| "source": "PPR", |
| "pubTypeList": {"pubType": ["Preprint"]}, |
| } |
| ] |
| } |
| } |
|
|
| with patch("httpx.AsyncClient") as mock_client: |
| mock_instance = AsyncMock() |
| mock_client.return_value.__aenter__.return_value = mock_instance |
|
|
| mock_resp = MagicMock() |
| mock_resp.json.return_value = mock_response |
| mock_resp.raise_for_status.return_value = None |
| mock_instance.get.return_value = mock_resp |
|
|
| results = await tool.search("test", max_results=5) |
|
|
| assert "PREPRINT" in results[0].content |
| assert results[0].citation.source == "preprint" |
|
|
| @pytest.mark.asyncio |
| async def test_search_empty_results(self, tool: EuropePMCTool) -> None: |
| """Test handling of empty results.""" |
| mock_response = {"resultList": {"result": []}} |
|
|
| with patch("httpx.AsyncClient") as mock_client: |
| mock_instance = AsyncMock() |
| mock_client.return_value.__aenter__.return_value = mock_instance |
|
|
| mock_resp = MagicMock() |
| mock_resp.json.return_value = mock_response |
| mock_resp.raise_for_status.return_value = None |
| mock_instance.get.return_value = mock_resp |
|
|
| results = await tool.search("nonexistent query xyz", max_results=5) |
|
|
| assert results == [] |
|
|
|
|
| @pytest.mark.integration |
| class TestEuropePMCIntegration: |
| """Integration tests with real API.""" |
|
|
| @pytest.mark.asyncio |
| async def test_real_api_call(self) -> None: |
| """Test actual API returns relevant results.""" |
| tool = EuropePMCTool() |
| results = await tool.search("long covid treatment", max_results=3) |
|
|
| assert len(results) > 0 |
| |
| titles = " ".join([r.citation.title.lower() for r in results]) |
| assert "covid" in titles or "sars" in titles |
|
|