Reputation: 319
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?
Upvotes: 1
Views: 2461
Reputation: 319
Following MrBean Bremen advice... After going through the documentation again, again, I learned quite a few important things. I also consumed a few tutorials, but ultimately, none of them solved my problem or at least were not, IMO, good at explaining what the hell I was doing.
I was able to mock class attributes and instance methods when all I wanted to was to mock an instance attribute. I also read many tutorials, which did not help me fully understand what I was doing either.
Eventually, after a desperate google search with a piece of my own code that should not yield any important results (i.e.: mocker.patch.object(Article, summary="abc", create=True)
), I came across the best tutorial I found all around the web over the last week, which finally helped me connect the docs.
The final solution for own my question is (docstring includes the tutorial that helped me):
def test_generate_summary(mocker):
"""See comprehensive guide to pytest using pytest-mock lib:
https://levelup.gitconnected.com/a-comprehensive-guide-to-pytest-3676f05df5a0
"""
mock_article = mocker.patch("app.utils.summarizer.Article")
mock_article().summary = "abc"
mocker.patch("app.utils.summarizer.nltk.data.find", return_value=None)
summary = summarizer.generate_summary("https://test-url.com")
assert summary == "abc"
Upvotes: 2