@@ -908,6 +908,68 @@ def test_get_variation_cmab_experiment_service_error(self):
908
908
# Verify logger was called
909
909
mock_logger .error .assert_any_call ('CMAB decision fetch failed with status: CMAB service error' )
910
910
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
+
911
973
def test_get_variation_cmab_experiment_forced_variation (self ):
912
974
"""Test get_variation with CMAB experiment when user has a forced variation."""
913
975
0 commit comments