Having some trouble understanding how to mock a class instance attribute. The class is defined by the package "newspaper3k", e.g.: from newspaper import Article.
I have been stuck on this for a while and I seem to be going nowhere even after looking at the documentation. Anyone can give me a pointer on this?
"""utils/summarizer.py module """
import nltk
from newspaper import Article
def generate_summary(url: str) -> str:
article = Article(url)
article.download()
article.parse()
try:
nltk.data.find("tokenizers/punkt")
except LookupError:
nltk.download("punkt")
finally:
article.nlp()
return article.summary
My current attempt looks like this... I am afraid I am confusing libraries and the way mocking is done in python with pytest.
from newspaper import Article
import app.utils.summarizer as summarizer
def test_generate_summary(mocker, monkeypatch):
article = mocker.MagicMock(Article)
type(article).summary = mocker.PropertyMock(return_value="abc")
# methods = {
# 'download.return_value': None,
# 'parse.return_value': None,
# 'nlp.return_value': None,
# }
# article_mock = mocker.MagicMock(summary="abc", **methods)
# monkeypatch.setattr("newspaper.article.Article", article_mock)
monkeypatch.setattr(Article, "download", lambda _: None)
monkeypatch.setattr(Article, "parse", lambda _: None)
monkeypatch.setattr(Article, "nlp", lambda _: None)
monkeypatch.setattr(
"nltk.data.find", lambda _: "https://test-url.com/resource?name=foo#bar"
)
summary = summarizer.generate_summary("https://test-url.com")
assert summary == "abc"
Any tips? Also, is there anyway I can mock "download", "parse" and, "nlp" methods more easily?
mocker.patchto actually patchArticleinstead of just creating a mock that will not be used. Second, if you patch it, it will be replaced by a mock, and each call on the mock will return another mock, so there is no need to patch the methods. Try to read some tutorials or examples on mocking first, there are plenty.