Skip to content

Commit 034b820

Browse files
committed
fix: mock scholarly module object in CI where scholarly is not installed
The scholarly package is an optional dependency. When not installed, the module-level variable is None, so patching scholarly.search_pubs directly raises AttributeError. Use patch.object on the pipeline module instead.
1 parent 4831cb8 commit 034b820

File tree

1 file changed

+22
-15
lines changed

1 file changed

+22
-15
lines changed

tests/test_pipeline_unit.py

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@
1515

1616
import pytest
1717
import requests
18-
from unittest.mock import patch
18+
from unittest.mock import patch, MagicMock
1919

2020
from onecite.pipeline import EnricherModule, FormatterModule, IdentifierModule
21+
import onecite.pipeline as _pipeline_mod
2122

2223

2324
# ---------------------------------------------------------------------------
@@ -452,9 +453,11 @@ def test_success(self):
452453
"eprint": "arXiv:1706.03762",
453454
}]
454455

455-
with patch("threading.Thread", ImmediateThread), \
456-
patch("time.sleep"), patch("time.time", return_value=1000.0), \
457-
patch("onecite.pipeline.scholarly.search_pubs", return_value=pubs):
456+
fake_scholarly = MagicMock()
457+
fake_scholarly.search_pubs = MagicMock(return_value=pubs)
458+
with patch.object(_pipeline_mod, "scholarly", fake_scholarly), \
459+
patch("threading.Thread", ImmediateThread), \
460+
patch("time.sleep"), patch("time.time", return_value=1000.0):
458461
results = ident._search_google_scholar("neurips paper", limit=1)
459462

460463
assert results[0]["source"] == "google_scholar"
@@ -464,10 +467,11 @@ def test_success(self):
464467

465468
def test_captcha_returns_empty(self):
466469
ident = IdentifierModule(use_google_scholar=True)
467-
with patch("threading.Thread", ImmediateThread), \
468-
patch("time.sleep"), patch("time.time", return_value=1000.0), \
469-
patch("onecite.pipeline.scholarly.search_pubs",
470-
side_effect=Exception("captcha blocked")):
470+
fake_scholarly = MagicMock()
471+
fake_scholarly.search_pubs = MagicMock(side_effect=Exception("captcha blocked"))
472+
with patch.object(_pipeline_mod, "scholarly", fake_scholarly), \
473+
patch("threading.Thread", ImmediateThread), \
474+
patch("time.sleep"), patch("time.time", return_value=1000.0):
471475
assert ident._search_google_scholar("q", limit=1) == []
472476

473477
def test_timeout_returns_empty(self):
@@ -748,9 +752,11 @@ def test_google_scholar_fetch_success(self):
748752
def _pubs(_q):
749753
yield {"pages": "123--130"}
750754

751-
with patch("threading.Thread", ImmediateThread), \
752-
patch("time.sleep"), patch("time.time", return_value=1000.0), \
753-
patch("onecite.pipeline.scholarly.search_pubs", side_effect=_pubs):
755+
fake_scholarly = MagicMock()
756+
fake_scholarly.search_pubs = MagicMock(side_effect=_pubs)
757+
with patch.object(_pipeline_mod, "scholarly", fake_scholarly), \
758+
patch("threading.Thread", ImmediateThread), \
759+
patch("time.sleep"), patch("time.time", return_value=1000.0):
754760
val = e._fetch_missing_field("pages", ["google_scholar_scraper"],
755761
{"title": "T", "author": "Doe, John", "year": "2020"})
756762

@@ -764,10 +770,11 @@ def test_google_scholar_timeout(self):
764770

765771
def test_google_scholar_worker_error(self):
766772
e = EnricherModule(use_google_scholar=True)
767-
with patch("threading.Thread", ImmediateThread), \
768-
patch("time.sleep"), patch("time.time", return_value=1000.0), \
769-
patch("onecite.pipeline.scholarly.search_pubs",
770-
side_effect=RuntimeError("boom")):
773+
fake_scholarly = MagicMock()
774+
fake_scholarly.search_pubs = MagicMock(side_effect=RuntimeError("boom"))
775+
with patch.object(_pipeline_mod, "scholarly", fake_scholarly), \
776+
patch("threading.Thread", ImmediateThread), \
777+
patch("time.sleep"), patch("time.time", return_value=1000.0):
771778
assert e._fetch_from_google_scholar("pages", {"title": "T"}) is None
772779

773780

0 commit comments

Comments
 (0)