"""Unit tests for PubMed tool.""" from unittest.mock import AsyncMock, MagicMock import pytest from src.tools.pubmed import PubMedTool # Sample PubMed XML response for mocking SAMPLE_PUBMED_XML = """ 12345678
Metformin in Alzheimer's Disease: A Systematic Review Metformin shows neuroprotective properties... Smith John 2024 01
""" class TestPubMedTool: """Tests for PubMedTool.""" @pytest.mark.asyncio async def test_search_returns_evidence(self, mocker): """PubMedTool should return Evidence objects from search.""" # Mock the HTTP responses mock_search_response = MagicMock() mock_search_response.json.return_value = {"esearchresult": {"idlist": ["12345678"]}} mock_search_response.raise_for_status = MagicMock() mock_fetch_response = MagicMock() mock_fetch_response.text = SAMPLE_PUBMED_XML mock_fetch_response.raise_for_status = MagicMock() mock_client = AsyncMock() mock_client.get = AsyncMock(side_effect=[mock_search_response, mock_fetch_response]) mock_client.__aenter__ = AsyncMock(return_value=mock_client) mock_client.__aexit__ = AsyncMock(return_value=None) mocker.patch("httpx.AsyncClient", return_value=mock_client) # Act tool = PubMedTool() results = await tool.search("metformin alzheimer") # Assert assert len(results) == 1 assert results[0].citation.source == "pubmed" assert "Metformin" in results[0].citation.title assert "12345678" in results[0].citation.url @pytest.mark.asyncio async def test_search_empty_results(self, mocker): """PubMedTool should return empty list when no results.""" mock_response = MagicMock() mock_response.json.return_value = {"esearchresult": {"idlist": []}} mock_response.raise_for_status = MagicMock() mock_client = AsyncMock() mock_client.get = AsyncMock(return_value=mock_response) mock_client.__aenter__ = AsyncMock(return_value=mock_client) mock_client.__aexit__ = AsyncMock(return_value=None) mocker.patch("httpx.AsyncClient", return_value=mock_client) tool = PubMedTool() results = await tool.search("xyznonexistentquery123") assert results == [] def test_parse_pubmed_xml(self): """PubMedTool should correctly parse XML.""" tool = PubMedTool() results = tool._parse_pubmed_xml(SAMPLE_PUBMED_XML) assert len(results) == 1 assert results[0].citation.source == "pubmed" assert "Smith John" in results[0].citation.authors @pytest.mark.asyncio async def test_search_preprocesses_query(self, mocker): """Test that queries are preprocessed before search.""" mock_search_response = MagicMock() mock_search_response.json.return_value = {"esearchresult": {"idlist": []}} mock_search_response.raise_for_status = MagicMock() mock_client = AsyncMock() mock_client.get = AsyncMock(return_value=mock_search_response) mock_client.__aenter__ = AsyncMock(return_value=mock_client) mock_client.__aexit__ = AsyncMock(return_value=None) mocker.patch("httpx.AsyncClient", return_value=mock_client) tool = PubMedTool() await tool.search("What drugs help with Long COVID?") # Verify call args call_args = mock_client.get.call_args params = call_args[1]["params"] term = params["term"] # "what" and "help" should be stripped assert "what" not in term.lower() assert "help" not in term.lower() # "long covid" should be expanded assert "PASC" in term or "post-COVID" in term