Reputation: 422
I am using requests to create a requests.Session
and set it up inside a function:
def create_web_session(cookie=None):
s = requests.Session()
if cookie is not None:
s.cookies.set("my_cookie_name", cookie)
return s
Sessions can be used as context managers. Can I use the function that returns the session (above) in a with
statement?
with create_web_session("my_cookie_value") as s:
s.get(...)
Or would I have to change the function that instead takes a session and sets it up inside the context manager:
with requests.Session() as s:
setup_web_session(s, "my_cookie_value")
s.get(...)
Running the former seemed to work however my unit tests failed which is why I asked this question. I am patching the create_web_session
and upon testing the s.get(...)
I am asserting that my mock gets called with .get()
however it seems to be session_mock.__enter__()
that is calling it. Is this expected behavior?
Here is an example:
# Function
def my_function():
s = create_web_session()
s.get("https://google.com")
s.close()
# Test
@patch("foo.bar.create_web_session")
def test_my_function(self, mock_create_web_session):
my_function()
mock_create_web_session.assert_called_once()
mock_create_web_session.return_value.get.assert_called_once()
mock_create_web_session.return_value.close.assert_called_once()
Once I change the function to use context managers:
def my_function():
with create_web_session() as s:
s.get("https://google.com")
The test fails with:
Expected 'get' to have been called once. Called 0 times.
Upvotes: 0
Views: 197
Reputation: 36043
Your create_web_session
is fine. The problem in the test is that while requests.Session.__enter__
simply returns back the same session, all methods on a mock return a fresh mock object. We can tell the mock to behave how we want and get a working test case like so:
def test_my_function(self, mock_create_web_session):
session = mock_create_web_session.return_value
session.__enter__.return_value = session
my_function()
mock_create_web_session.assert_called_once()
session.get.assert_called_once()
session.__exit__.assert_called_once()
Note that I assert __exit__
is called, not close
, because the mock doesn't know anything about close
or real sessions.
Upvotes: 1