75 lines
3.3 KiB
Python
75 lines
3.3 KiB
Python
|
|
import sys
|
|
import os
|
|
import unittest
|
|
from unittest.mock import MagicMock
|
|
|
|
# Adjust path to find backend modules. We need 'backend' to be in path so 'src' is top level.
|
|
# Script is in backend/../scratch/verify_timeout.py
|
|
# We want abs path to backend/
|
|
project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
|
|
backend_path = os.path.join(project_root, 'backend')
|
|
sys.path.append(backend_path)
|
|
|
|
# Mock dependencies to avoid database connections or complex setups
|
|
# We need to mock modules BEFORE they are imported by the real code
|
|
sys.modules['src.models'] = MagicMock()
|
|
sys.modules['src.models.api_token'] = MagicMock()
|
|
sys.modules['src.models.base'] = MagicMock()
|
|
|
|
# Now import the client from the src package
|
|
from src.services.garmin.client import GarminClient
|
|
import garth
|
|
|
|
|
|
class TestGarminTimeout(unittest.TestCase):
|
|
def test_timeout_injection(self):
|
|
# Initialize client (mocking credentials to avoid network)
|
|
client = GarminClient("test", "test")
|
|
|
|
# We want to verify that client.client.garth.sess.request (which we patched) adds 'timeout'
|
|
# But we must be careful: we patched the INSTANCE method on init.
|
|
|
|
# We need to mock the ORIGINAL request method that our wrapper calls,
|
|
# OR just mock the return value if we don't care about the original running.
|
|
# content of patch:
|
|
# original_request = self.client.garth.sess.request
|
|
# ... return original_request(...)
|
|
|
|
# So if we mock 'original_request', how do we access it?
|
|
# It's captured in the closure of 'request_with_timeout'.
|
|
|
|
# Instead, we can inspect what our wrapper does.
|
|
# But 'original_request' is the REAL request method of requests.Session (since we didn't mock it before Init).
|
|
# We don't want to make a real network call.
|
|
|
|
# So we should Mock `requests.Session.request` BEFORE initializing GarminClient?
|
|
# But `GarminClient` init creates `garminconnect.Garmin` which creates `garth.Client` which creates `requests.Session`.
|
|
|
|
# We can mock `requests.Session.request` globally?
|
|
with unittest.mock.patch('requests.Session.request') as mock_session_request:
|
|
# Re-init client so it picks up the mock as 'original_request' ??
|
|
# No, 'original_request = ...sess.request' grabs the bound method.
|
|
# If we patch Session.request, new instances will have the mock.
|
|
|
|
client = GarminClient("test", "test")
|
|
# Now `client.client.garth.sess.request` is our wrapper.
|
|
# And `original_request` (inside wrapper) should be the mock_session_request (bound).
|
|
|
|
# Call our wrapper
|
|
client.client.garth.sess.request("GET", "http://example.com")
|
|
|
|
# Verify the mock was called with timeout
|
|
kwargs = mock_session_request.call_args.kwargs
|
|
print(f"Call kwargs: {kwargs}")
|
|
|
|
self.assertIn('timeout', kwargs, "Timeout parameter missing from request")
|
|
self.assertEqual(kwargs['timeout'], 30, "Timeout value incorrect")
|
|
|
|
if __name__ == '__main__':
|
|
try:
|
|
unittest.main()
|
|
except SystemExit as e:
|
|
# Prevent unittest from exiting so we can see output if run via run_command with multiple steps
|
|
pass
|