149149 ]
150150}
151151
152+ mock_balance_empty = {}
153+
154+ mock_balance_invalid1 = {
155+ "executionResult" : "INVALID" ,
156+ }
157+
158+ mock_balance_invalid2 = {
159+ "executionResult" : "SUCCESS" ,
160+ "extraInformation" : {"foo" : "bar" },
161+ }
162+
152163mock_balance_success = {
153164 "executionResult" : "SUCCESS" ,
154165 "extraInformation" : {
@@ -509,21 +520,18 @@ def test_bad_secrets(mocker):
509520
510521def test_requests (mocker , requests_mock ):
511522 """
512- Test getting chart of accounts from upstream API
523+ Test _chart_requests and _balance_requests
513524
514525 Relies on `requests-mock.Mocker` fixture to inject mock `requests` responses.
515526 Because requests-mock creates a requests transport adapter, responses are
516- global and not thread-safe . Run tests sequentially to maintain control of
517- response order.
527+ global (across all tests) . Run all related assertions sequentially to maintain
528+ control of the response order.
518529 """
519530
520531 # inject mock responses into `requests`
521532 login_mock = requests_mock .post (mips_api ._mip_url_login , json = mock_token )
522533 segment_mock = requests_mock .get (mips_api ._mip_url_coa_segments , json = mock_segments )
523534 account_mock = requests_mock .get (mips_api ._mip_url_coa_accounts , json = mock_accounts )
524- balance_mock = requests_mock .post (
525- mips_api ._mip_url_current_balance , json = mock_balance_success
526- )
527535 logout_mock = requests_mock .post (mips_api ._mip_url_logout )
528536
529537 # also mock today's date
@@ -547,13 +555,14 @@ def test_requests(mocker, requests_mock):
547555 assert logout_mock .call_count == 1
548556
549557 # get current balance from mip
558+ balance_mock = requests_mock .post (
559+ mips_api ._mip_url_current_balance , json = mock_balance_success
560+ )
550561 balance_dict = mips_api ._balance_requests (mock_org_name , mock_secrets )
551562 assert balance_mock .call_count == 1
552563 assert balance_dict == mock_balance_success
553564
554- # begin a second test with an alternate requests response
555-
556- # inject new mock response with an Exception
565+ # inject new mock response with an Exception for coa segments
557566 requests_mock .get (mips_api ._mip_url_coa_segments , exc = Exception )
558567
559568 # assert logout is called when an exception is raised
@@ -587,6 +596,40 @@ def test_cache_write(mocker):
587596 mips_api ._s3_cache_write (expected_coa_dict_raw , mock_s3_bucket , mock_s3_chart )
588597
589598
599+ @pytest .mark .parametrize (
600+ "api_response,cache_response" ,
601+ [
602+ (mock_balance_success , None ),
603+ (None , mock_balance_success ),
604+ (mock_balance_success , mock_balance_success ),
605+ ],
606+ )
607+ def test_balance_cache (mocker , api_response , cache_response ):
608+ """Test balance_cache() with no upstream response"""
609+ mocker .patch (
610+ "mips_api._balance_requests" ,
611+ autospec = True ,
612+ return_value = api_response ,
613+ )
614+ mocker .patch (
615+ "mips_api._s3_cache_read" ,
616+ autospec = True ,
617+ return_value = cache_response ,
618+ )
619+ mocker .patch (
620+ "mips_api._s3_cache_write" ,
621+ autospec = True ,
622+ )
623+
624+ found_dict = mips_api .balance_cache (
625+ mock_org_name ,
626+ mock_secrets ,
627+ mock_s3_bucket ,
628+ mock_s3_chart ,
629+ )
630+ assert found_dict == mock_balance_success
631+
632+
590633@pytest .mark .parametrize (
591634 "chart_response,cache_response" ,
592635 [
@@ -724,6 +767,24 @@ def test_process_chart(
724767 assert processed_chart == expected_dict
725768
726769
770+ @pytest .mark .parametrize (
771+ "bal_dict, coa_dict, fail" ,
772+ [
773+ (mock_balance_empty , expected_coa_dict_processed_other , True ),
774+ (mock_balance_invalid1 , expected_coa_dict_processed_other , True ),
775+ (mock_balance_invalid2 , expected_coa_dict_processed_other , True ),
776+ (mock_balance_success , expected_coa_dict_processed_other , False ),
777+ ],
778+ )
779+ def test_process_balance (bal_dict , coa_dict , fail ):
780+ if fail :
781+ with pytest .raises (Exception ):
782+ mips_api .process_balance (bal_dict , coa_dict )
783+ else :
784+ found_rows = mips_api .process_balance (bal_dict , coa_dict )
785+ assert found_rows == expected_balance_rows
786+
787+
727788@pytest .mark .parametrize (
728789 "params,expected_bool" ,
729790 [
@@ -820,7 +881,7 @@ def test_lambda_handler_no_env(invalid_event):
820881 assert ret ["statusCode" ] == 500
821882
822883
823- def _test_with_env (mocker , event , code , body = None , error = None , use_json = True ):
884+ def _test_with_env (mocker , event , code , body = None , error = None , text = None ):
824885 """Keep lambda_handler tests DRY"""
825886
826887 # mock environment variables
@@ -860,17 +921,18 @@ def _test_with_env(mocker, event, code, body=None, error=None, use_json=True):
860921 ret = mips_api .lambda_handler (event , None )
861922 assert ret ["statusCode" ] == code
862923
863- if use_json :
924+ if text is not None :
925+ assert ret ["body" ] == text
926+
927+ else :
864928 json_body = json .loads (ret ["body" ])
865929
930+ if body is not None :
931+ assert json_body == body
932+
866933 if error is not None :
867934 assert json_body ["error" ] == error
868935
869- elif body is not None :
870- assert json_body == body
871- else :
872- assert ret ["body" ] == body
873-
874936
875937def test_lambda_handler_invalid_path (invalid_event , mocker ):
876938 """Test event with no path"""
@@ -904,9 +966,7 @@ def test_lambda_handler_accounts_priority(accounts_priority_event, mocker):
904966def test_lambda_handler_balance (balances_event , mocker ):
905967 """Test tag-list event"""
906968
907- _test_with_env (
908- mocker , balances_event , 200 , body = expected_balance_csv , use_json = False
909- )
969+ _test_with_env (mocker , balances_event , 200 , text = expected_balance_csv )
910970
911971
912972def test_lambda_handler_tags (tags_event , mocker ):
0 commit comments