@@ -26,6 +26,18 @@ def json(self):
2626 return self .json_data
2727
2828
29+ class MockResponseWithRaiseForStatus :
30+ def __init__ (self , json_data , status_code ):
31+ self .json_data = json_data
32+ self .status_code = status_code
33+
34+ def json (self ):
35+ return self .json_data
36+
37+ def raise_for_status (self ):
38+ pass
39+
40+
2941class MockSession :
3042 def __init__ (self , json_data , status_code ):
3143 self .response = MockResponse (json_data , status_code )
@@ -58,10 +70,45 @@ def get(self, *args, **kwargs):
5870 return MockResponse (json .load (f ), 200 )
5971
6072
73+ class MockSessionTokenRefresh :
74+ def __init__ (self , json_data , status_code ):
75+ self .response = MockResponse (json_data , status_code )
76+
77+ def mount (self , * args , ** kwargs ):
78+ return
79+
80+ def get (self , * args , ** kwargs ):
81+ endpoint_url = kwargs ['url' ]
82+ parsed_url = urlparse (endpoint_url )
83+ if parsed_url .path .endswith ('Patient/' ):
84+ # patient
85+ return self .response
86+ else :
87+ raise ValueError ("Unexpected GET path={}" .format (parsed_url .path ))
88+
89+
6190def success_fhir_patient_request_mock (* args , ** kwargs ):
6291 return MockSession ({"resourceType" : "Patient" , "id" : "-20140000010000" }, 200 )
6392
6493
94+ def mocked_token_refresh_post (* args , ** kwargs ):
95+ endpoint_url = kwargs ['url' ]
96+ parsed_url = urlparse (endpoint_url )
97+ if parsed_url .path .endswith ('token/' ):
98+ # auth token - refreshed
99+ expires_at_str = str (datetime .datetime .now (datetime .timezone .utc ) + datetime .timedelta (seconds = 36000 ))
100+ return MockResponseWithRaiseForStatus ({"access_token" : "fake_access_token" ,
101+ "refresh_token" : "fake_refresh_token" ,
102+ "expires_at" : expires_at_str ,
103+ "patient" : "-20140000010000" }, 200 )
104+ else :
105+ raise ValueError ("Unexpected POST path={}" .format (parsed_url .path ))
106+
107+
108+ def success_fhir_patient_request_refresh_token_mock (* args , ** kwargs ):
109+ return MockSessionTokenRefresh ({"resourceType" : "Patient" , "id" : "-20140000010000" }, 200 )
110+
111+
65112def success_fhir_coverage_request_mock (* args , ** kwargs ):
66113 return MockSession ({"resourceType" : "Bundle" , "id" : "aaa-111-111-111-aaaa" }, 200 )
67114
@@ -101,6 +148,21 @@ def generate_mock_config():
101148 }
102149
103150
151+ def generate_mock_config_w_expired_access_token ():
152+ return {
153+ "params" : {},
154+ "auth_token" : AuthorizationToken (
155+ {
156+ "access_token" : "fake_access_token" ,
157+ "refresh_token" : "fake_refresh_token" ,
158+ "expires_at" : datetime .datetime .now (datetime .timezone .utc )
159+ - datetime .timedelta (seconds = 36000 ),
160+ "patient" : "-20140000010000" ,
161+ }
162+ ),
163+ }
164+
165+
104166class TestAPI (unittest .TestCase ):
105167 @mock .patch ("requests.Session" , side_effect = success_fhir_patient_request_mock )
106168 def test_successful_fhir_patient_request (self , get_request_mock ):
@@ -151,6 +213,40 @@ def test_successful_fhir_eob_pages_request(self, get_request_mock):
151213 self .assertEqual (len (pages ["pages" ]), 6 )
152214 self .assertEqual (get_request_mock .call_count , 6 )
153215
216+ @mock .patch ("requests.post" , side_effect = mocked_token_refresh_post )
217+ @mock .patch ("requests.Session" , side_effect = success_fhir_patient_request_refresh_token_mock )
218+ def test_successful_fhir_request_token_refreshed (self , post_mock , get_mock ):
219+ bb = BlueButton (config = MOCK_BB_CONFIG )
220+ config = generate_mock_config_w_expired_access_token ()
221+ response = bb .get_patient_data (config )
222+ self .assertTrue (config ['auth_token' ].access_token_expired ())
223+ self .assertIsNotNone (response ["auth_token" ])
224+ self .assertFalse (response ['auth_token' ].access_token_expired ())
225+ self .assertEqual (response ["response" ].status_code , 200 )
226+ self .assertEqual (response ["response" ].json ()["id" ], "-20140000010000" )
227+ self .assertEqual (response ["response" ].json ()["resourceType" ], "Patient" )
228+ # mock post called once for token refresh
229+ self .assertEqual (post_mock .call_count , 1 )
230+ # mock get called once for fhir resource
231+ self .assertEqual (get_mock .call_count , 1 )
232+
233+ @mock .patch ("requests.post" , side_effect = mocked_token_refresh_post )
234+ @mock .patch ("requests.Session" , side_effect = success_fhir_patient_request_refresh_token_mock )
235+ def test_successful_fhir_request_token_refresh_disabled (self , get_mock , post_mock ):
236+ bb = BlueButton (config = "./tests/test_configs/json/bluebutton-sample-config-disable-token-refresh-on-expire.json" )
237+ config = generate_mock_config_w_expired_access_token ()
238+ response = bb .get_patient_data (config )
239+ self .assertTrue (config ['auth_token' ].access_token_expired ())
240+ self .assertIsNotNone (response ["auth_token" ])
241+ self .assertTrue (response ['auth_token' ].access_token_expired ())
242+ self .assertEqual (response ["response" ].status_code , 200 )
243+ self .assertEqual (response ["response" ].json ()["id" ], "-20140000010000" )
244+ self .assertEqual (response ["response" ].json ()["resourceType" ], "Patient" )
245+ # mock post for toekn not called
246+ self .assertEqual (post_mock .call_count , 0 )
247+ # mock get called once for fhir resource
248+ self .assertEqual (get_mock .call_count , 1 )
249+
154250 @mock .patch ("requests.Session" , side_effect = success_fhir_profile_request_mock )
155251 def test_successful_fhir_profile_request (self , get_request_mock ):
156252 bb = BlueButton (config = MOCK_BB_CONFIG )
0 commit comments