@@ -908,6 +908,68 @@ def test_get_variation_cmab_experiment_service_error(self):
908908 # Verify logger was called
909909 mock_logger .error .assert_any_call ('CMAB decision fetch failed with status: CMAB service error' )
910910
911+ def test_get_variation_cmab_experiment_deep_mock_500_error (self ):
912+ """Test the full flow of a CMAB experiment with a 500 error from the HTTP request layer."""
913+ import requests
914+ from optimizely .exceptions import CmabFetchError
915+ from optimizely .helpers .enums import Errors
916+
917+ # Create a user context
918+ user = optimizely_user_context .OptimizelyUserContext (
919+ optimizely_client = None ,
920+ logger = None ,
921+ user_id = "test_user" ,
922+ user_attributes = {}
923+ )
924+
925+ # Create a CMAB experiment
926+ cmab_experiment = entities .Experiment (
927+ '111150' ,
928+ 'cmab_experiment' ,
929+ 'Running' ,
930+ '111150' ,
931+ [], # No audience IDs
932+ {},
933+ [entities .Variation ('111151' , 'variation_1' )],
934+ [{'entityId' : '111151' , 'endOfRange' : 10000 }],
935+ cmab = {'trafficAllocation' : 5000 }
936+ )
937+
938+ # Define HTTP error details
939+ http_error = requests .exceptions .HTTPError ("500 Server Error" )
940+ error_message = Errors .CMAB_FETCH_FAILED .format (http_error )
941+ detailed_error_message = Errors .CMAB_FETCH_FAILED_DETAILED .format (cmab_experiment .key , error_message )
942+
943+ # Set up mocks for the entire call chain
944+ with mock .patch ('optimizely.helpers.experiment.is_experiment_running' , return_value = True ), \
945+ mock .patch ('optimizely.helpers.audience.does_user_meet_audience_conditions' , return_value = [True , []]), \
946+ mock .patch ('optimizely.bucketer.Bucketer.bucket_to_entity_id' , return_value = ['$' , []]), \
947+ mock .patch .object (self .decision_service .cmab_service , 'get_decision' ,
948+ side_effect = lambda * args , ** kwargs : self .decision_service .cmab_service ._fetch_decision (* args , ** kwargs )), \
949+ mock .patch .object (self .decision_service .cmab_service , '_fetch_decision' ,
950+ side_effect = lambda * args , ** kwargs : self .decision_service .cmab_service .cmab_client .fetch_decision (* args , ** kwargs )), \
951+ mock .patch .object (self .decision_service .cmab_service .cmab_client , 'fetch_decision' ,
952+ side_effect = lambda * args , ** kwargs : self .decision_service .cmab_service .cmab_client ._do_fetch (* args , ** kwargs )), \
953+ mock .patch .object (self .decision_service .cmab_service .cmab_client , '_do_fetch' ,
954+ side_effect = CmabFetchError (error_message )), \
955+ mock .patch .object (self .decision_service , 'logger' ) as mock_logger :
956+
957+ # Call get_variation with the CMAB experiment
958+ variation , reasons , cmab_uuid = self .decision_service .get_variation (
959+ self .project_config ,
960+ cmab_experiment ,
961+ user ,
962+ None
963+ )
964+
965+ # Verify we get no variation due to CMAB service error
966+ self .assertIsNone (variation )
967+ self .assertIsNone (cmab_uuid )
968+ self .assertIn (detailed_error_message , reasons )
969+
970+ # Verify logger was called with the specific 500 error
971+ mock_logger .error .assert_any_call (detailed_error_message )
972+
911973 def test_get_variation_cmab_experiment_forced_variation (self ):
912974 """Test get_variation with CMAB experiment when user has a forced variation."""
913975
0 commit comments