diff --git a/tests/unit/modules/dcnm/dcnm_fabric/fixtures/responses_FabricDetailsByName.json b/tests/unit/modules/dcnm/dcnm_fabric/fixtures/responses_FabricDetailsByName.json index baaf6d8c3..596041518 100644 --- a/tests/unit/modules/dcnm/dcnm_fabric/fixtures/responses_FabricDetailsByName.json +++ b/tests/unit/modules/dcnm/dcnm_fabric/fixtures/responses_FabricDetailsByName.json @@ -4818,5 +4818,318 @@ "METHOD": "GET", "REQUEST_PATH": "https://172.22.150.244:443/appcenter/cisco/ndfc/api/v1/rest/control/fabrics", "RETURN_CODE": 200 + }, + "test_fabric_update_bulk_00130a": { + "DATA": [ + { + "asn": "65001", + "createdOn": 1711411093680, + "deviceType": "n9k", + "fabricId": "FABRIC-2", + "fabricName": "f1", + "fabricTechnology": "VXLANFabric", + "fabricTechnologyFriendly": "VXLAN EVPN", + "fabricType": "Switch_Fabric", + "fabricTypeFriendly": "Switch Fabric", + "id": 2, + "modifiedOn": 1711411096857, + "networkExtensionTemplate": "Default_Network_Extension_Universal", + "networkTemplate": "Default_Network_Universal", + "nvPairs": { + "AAA_REMOTE_IP_ENABLED": "false", + "AAA_SERVER_CONF": "", + "ACTIVE_MIGRATION": "false", + "ADVERTISE_PIP_BGP": "false", + "ADVERTISE_PIP_ON_BORDER": "true", + "AGENT_INTF": "eth0", + "AI_ML_QOS_POLICY": "AI_Fabric_QOS_400G", + "ALLOW_NXC": "true", + "ALLOW_NXC_PREV": "true", + "ANYCAST_BGW_ADVERTISE_PIP": "false", + "ANYCAST_GW_MAC": "2020.0000.00aa", + "ANYCAST_LB_ID": "", + "ANYCAST_RP_IP_RANGE": "10.254.254.0/24", + "ANYCAST_RP_IP_RANGE_INTERNAL": "", + "AUTO_SYMMETRIC_DEFAULT_VRF": "false", + "AUTO_SYMMETRIC_VRF_LITE": "false", + "AUTO_UNIQUE_VRF_LITE_IP_PREFIX": "false", + "AUTO_UNIQUE_VRF_LITE_IP_PREFIX_PREV": "false", + "AUTO_VRFLITE_IFC_DEFAULT_VRF": "false", + "BANNER": "", + "BFD_AUTH_ENABLE": "false", + "BFD_AUTH_KEY": "", + "BFD_AUTH_KEY_ID": "", + "BFD_ENABLE": "false", + "BFD_ENABLE_PREV": "", + "BFD_IBGP_ENABLE": "false", + "BFD_ISIS_ENABLE": "false", + "BFD_OSPF_ENABLE": "false", + "BFD_PIM_ENABLE": "false", + "BGP_AS": "65001", + "BGP_AS_PREV": "65001", + "BGP_AUTH_ENABLE": "false", + "BGP_AUTH_KEY": "", + "BGP_AUTH_KEY_TYPE": "3", + "BGP_LB_ID": "0", + "BOOTSTRAP_CONF": "", + "BOOTSTRAP_ENABLE": "false", + "BOOTSTRAP_ENABLE_PREV": "false", + "BOOTSTRAP_MULTISUBNET": "#Scope_Start_IP, Scope_End_IP, Scope_Default_Gateway, Scope_Subnet_Prefix", + "BOOTSTRAP_MULTISUBNET_INTERNAL": "", + "BRFIELD_DEBUG_FLAG": "Disable", + "BROWNFIELD_NETWORK_NAME_FORMAT": "Auto_Net_VNI$$VNI$$_VLAN$$VLAN_ID$$", + "BROWNFIELD_SKIP_OVERLAY_NETWORK_ATTACHMENTS": "false", + "CDP_ENABLE": "false", + "COPP_POLICY": "strict", + "DCI_SUBNET_RANGE": "10.33.0.0/16", + "DCI_SUBNET_TARGET_MASK": "30", + "DEAFULT_QUEUING_POLICY_CLOUDSCALE": "queuing_policy_default_8q_cloudscale", + "DEAFULT_QUEUING_POLICY_OTHER": "queuing_policy_default_other", + "DEAFULT_QUEUING_POLICY_R_SERIES": "queuing_policy_default_r_series", + "DEFAULT_VRF_REDIS_BGP_RMAP": "", + "DEPLOYMENT_FREEZE": "false", + "DHCP_ENABLE": "false", + "DHCP_END": "", + "DHCP_END_INTERNAL": "", + "DHCP_IPV6_ENABLE": "", + "DHCP_IPV6_ENABLE_INTERNAL": "", + "DHCP_START": "", + "DHCP_START_INTERNAL": "", + "DNS_SERVER_IP_LIST": "", + "DNS_SERVER_VRF": "", + "DOMAIN_NAME_INTERNAL": "", + "ENABLE_AAA": "false", + "ENABLE_AGENT": "false", + "ENABLE_AI_ML_QOS_POLICY": "false", + "ENABLE_AI_ML_QOS_POLICY_FLAP": "false", + "ENABLE_DEFAULT_QUEUING_POLICY": "false", + "ENABLE_EVPN": "true", + "ENABLE_FABRIC_VPC_DOMAIN_ID": "false", + "ENABLE_FABRIC_VPC_DOMAIN_ID_PREV": "false", + "ENABLE_L3VNI_NO_VLAN": "false", + "ENABLE_MACSEC": "false", + "ENABLE_NETFLOW": "false", + "ENABLE_NETFLOW_PREV": "false", + "ENABLE_NGOAM": "true", + "ENABLE_NXAPI": "true", + "ENABLE_NXAPI_HTTP": "true", + "ENABLE_PBR": "false", + "ENABLE_PVLAN": "false", + "ENABLE_PVLAN_PREV": "false", + "ENABLE_SGT": "false", + "ENABLE_SGT_PREV": "false", + "ENABLE_TENANT_DHCP": "true", + "ENABLE_TRM": "false", + "ENABLE_VPC_PEER_LINK_NATIVE_VLAN": "false", + "ESR_OPTION": "PBR", + "EXTRA_CONF_INTRA_LINKS": "", + "EXTRA_CONF_LEAF": "", + "EXTRA_CONF_SPINE": "", + "EXTRA_CONF_TOR": "", + "EXT_FABRIC_TYPE": "", + "FABRIC_INTERFACE_TYPE": "p2p", + "FABRIC_MTU": "9216", + "FABRIC_MTU_PREV": "9216", + "FABRIC_NAME": "f1", + "FABRIC_TYPE": "Switch_Fabric", + "FABRIC_VPC_DOMAIN_ID": "", + "FABRIC_VPC_DOMAIN_ID_PREV": "", + "FABRIC_VPC_QOS": "false", + "FABRIC_VPC_QOS_POLICY_NAME": "spine_qos_for_fabric_vpc_peering", + "FEATURE_PTP": "false", + "FEATURE_PTP_INTERNAL": "false", + "FF": "Easy_Fabric", + "GRFIELD_DEBUG_FLAG": "Disable", + "HD_TIME": "180", + "HOST_INTF_ADMIN_STATE": "true", + "IBGP_PEER_TEMPLATE": "", + "IBGP_PEER_TEMPLATE_LEAF": "", + "INBAND_DHCP_SERVERS": "", + "INBAND_MGMT": "false", + "INBAND_MGMT_PREV": "false", + "ISIS_AREA_NUM": "0001", + "ISIS_AREA_NUM_PREV": "", + "ISIS_AUTH_ENABLE": "false", + "ISIS_AUTH_KEY": "", + "ISIS_AUTH_KEYCHAIN_KEY_ID": "", + "ISIS_AUTH_KEYCHAIN_NAME": "", + "ISIS_LEVEL": "level-2", + "ISIS_OVERLOAD_ELAPSE_TIME": "", + "ISIS_OVERLOAD_ENABLE": "", + "ISIS_P2P_ENABLE": "", + "L2_HOST_INTF_MTU": "9216", + "L2_HOST_INTF_MTU_PREV": "9216", + "L2_SEGMENT_ID_RANGE": "30000-49000", + "L3VNI_MCAST_GROUP": "", + "L3_PARTITION_ID_RANGE": "50000-59000", + "LINK_STATE_ROUTING": "ospf", + "LINK_STATE_ROUTING_TAG": "UNDERLAY", + "LINK_STATE_ROUTING_TAG_PREV": "UNDERLAY", + "LOOPBACK0_IPV6_RANGE": "", + "LOOPBACK0_IP_RANGE": "10.2.0.0/22", + "LOOPBACK1_IPV6_RANGE": "", + "LOOPBACK1_IP_RANGE": "10.3.0.0/22", + "MACSEC_ALGORITHM": "", + "MACSEC_CIPHER_SUITE": "", + "MACSEC_FALLBACK_ALGORITHM": "", + "MACSEC_FALLBACK_KEY_STRING": "", + "MACSEC_KEY_STRING": "", + "MACSEC_REPORT_TIMER": "", + "MGMT_GW": "", + "MGMT_GW_INTERNAL": "", + "MGMT_PREFIX": "", + "MGMT_PREFIX_INTERNAL": "", + "MGMT_V6PREFIX": "", + "MGMT_V6PREFIX_INTERNAL": "", + "MPLS_HANDOFF": "false", + "MPLS_ISIS_AREA_NUM": "0001", + "MPLS_ISIS_AREA_NUM_PREV": "", + "MPLS_LB_ID": "", + "MPLS_LOOPBACK_IP_RANGE": "", + "MSO_CONNECTIVITY_DEPLOYED": "", + "MSO_CONTROLER_ID": "", + "MSO_SITE_GROUP_NAME": "", + "MSO_SITE_ID": "", + "MST_INSTANCE_RANGE": "", + "MULTICAST_GROUP_SUBNET": "239.1.1.0/25", + "NETFLOW_EXPORTER_LIST": "", + "NETFLOW_MONITOR_LIST": "", + "NETFLOW_RECORD_LIST": "", + "NETWORK_VLAN_RANGE": "2300-2999", + "NTP_SERVER_IP_LIST": "", + "NTP_SERVER_VRF": "", + "NVE_LB_ID": "1", + "NXAPI_HTTPS_PORT": "443", + "NXAPI_HTTP_PORT": "80", + "NXC_DEST_VRF": "", + "NXC_PROXY_PORT": "8080", + "NXC_PROXY_SERVER": "", + "NXC_SRC_INTF": "", + "OBJECT_TRACKING_NUMBER_RANGE": "100-299", + "OSPF_AREA_ID": "0.0.0.0", + "OSPF_AUTH_ENABLE": "false", + "OSPF_AUTH_KEY": "", + "OSPF_AUTH_KEY_ID": "", + "OVERLAY_MODE": "cli", + "OVERLAY_MODE_PREV": "cli", + "OVERWRITE_GLOBAL_NXC": "false", + "PER_VRF_LOOPBACK_AUTO_PROVISION": "false", + "PER_VRF_LOOPBACK_AUTO_PROVISION_PREV": "false", + "PER_VRF_LOOPBACK_AUTO_PROVISION_V6": "false", + "PER_VRF_LOOPBACK_AUTO_PROVISION_V6_PREV": "false", + "PER_VRF_LOOPBACK_IP_RANGE": "", + "PER_VRF_LOOPBACK_IP_RANGE_V6": "", + "PHANTOM_RP_LB_ID1": "", + "PHANTOM_RP_LB_ID2": "", + "PHANTOM_RP_LB_ID3": "", + "PHANTOM_RP_LB_ID4": "", + "PIM_HELLO_AUTH_ENABLE": "false", + "PIM_HELLO_AUTH_KEY": "", + "PM_ENABLE": "false", + "PM_ENABLE_PREV": "false", + "POWER_REDUNDANCY_MODE": "ps-redundant", + "PREMSO_PARENT_FABRIC": "", + "PTP_DOMAIN_ID": "", + "PTP_LB_ID": "", + "REPLICATION_MODE": "Multicast", + "ROUTER_ID_RANGE": "", + "ROUTE_MAP_SEQUENCE_NUMBER_RANGE": "1-65534", + "RP_COUNT": "2", + "RP_LB_ID": "254", + "RP_MODE": "asm", + "RR_COUNT": "2", + "SEED_SWITCH_CORE_INTERFACES": "", + "SERVICE_NETWORK_VLAN_RANGE": "3000-3199", + "SGT_ID_RANGE": "", + "SGT_NAME_PREFIX": "", + "SGT_PREPROVISION": "", + "SITE_ID": "65001", + "SLA_ID_RANGE": "10000-19999", + "SNMP_SERVER_HOST_TRAP": "true", + "SPINE_COUNT": "0", + "SPINE_SWITCH_CORE_INTERFACES": "", + "SSPINE_ADD_DEL_DEBUG_FLAG": "Disable", + "SSPINE_COUNT": "0", + "STATIC_UNDERLAY_IP_ALLOC": "false", + "STP_BRIDGE_PRIORITY": "", + "STP_ROOT_OPTION": "unmanaged", + "STP_VLAN_RANGE": "", + "STRICT_CC_MODE": "false", + "SUBINTERFACE_RANGE": "2-511", + "SUBNET_RANGE": "10.4.0.0/16", + "SUBNET_TARGET_MASK": "30", + "SYSLOG_SERVER_IP_LIST": "", + "SYSLOG_SERVER_VRF": "", + "SYSLOG_SEV": "", + "TCAM_ALLOCATION": "true", + "TOPDOWN_CONFIG_RM_TRACKING": "notstarted", + "UNDERLAY_IS_V6": "false", + "UNNUM_BOOTSTRAP_LB_ID": "", + "UNNUM_DHCP_END": "", + "UNNUM_DHCP_END_INTERNAL": "", + "UNNUM_DHCP_START": "", + "UNNUM_DHCP_START_INTERNAL": "", + "UPGRADE_FROM_VERSION": "", + "USE_LINK_LOCAL": "true", + "V6_SUBNET_RANGE": "", + "V6_SUBNET_TARGET_MASK": "126", + "VPC_AUTO_RECOVERY_TIME": "360", + "VPC_DELAY_RESTORE": "150", + "VPC_DELAY_RESTORE_TIME": "60", + "VPC_DOMAIN_ID_RANGE": "1-1000", + "VPC_ENABLE_IPv6_ND_SYNC": "true", + "VPC_PEER_KEEP_ALIVE_OPTION": "management", + "VPC_PEER_LINK_PO": "500", + "VPC_PEER_LINK_VLAN": "3600", + "VRF_LITE_AUTOCONFIG": "Manual", + "VRF_VLAN_RANGE": "2000-2299", + "abstract_anycast_rp": "anycast_rp", + "abstract_bgp": "base_bgp", + "abstract_bgp_neighbor": "evpn_bgp_rr_neighbor", + "abstract_bgp_rr": "evpn_bgp_rr", + "abstract_dhcp": "base_dhcp", + "abstract_extra_config_bootstrap": "extra_config_bootstrap_11_1", + "abstract_extra_config_leaf": "extra_config_leaf", + "abstract_extra_config_spine": "extra_config_spine", + "abstract_extra_config_tor": "extra_config_tor", + "abstract_feature_leaf": "base_feature_leaf_upg", + "abstract_feature_spine": "base_feature_spine_upg", + "abstract_isis": "base_isis_level2", + "abstract_isis_interface": "isis_interface", + "abstract_loopback_interface": "int_fabric_loopback_11_1", + "abstract_multicast": "base_multicast_11_1", + "abstract_ospf": "base_ospf", + "abstract_ospf_interface": "ospf_interface_11_1", + "abstract_pim_interface": "pim_interface", + "abstract_route_map": "route_map", + "abstract_routed_host": "int_routed_host", + "abstract_trunk_host": "int_trunk_host", + "abstract_vlan_interface": "int_fabric_vlan_11_1", + "abstract_vpc_domain": "base_vpc_domain_11_1", + "default_network": "Default_Network_Universal", + "default_pvlan_sec_network": "", + "default_vrf": "Default_VRF_Universal", + "enableRealTimeBackup": "", + "enableScheduledBackup": "", + "network_extension_template": "Default_Network_Extension_Universal", + "scheduledTime": "", + "temp_anycast_gateway": "anycast_gateway", + "temp_vpc_domain_mgmt": "vpc_domain_mgmt", + "temp_vpc_peer_link": "int_vpc_peer_link_po", + "vrf_extension_template": "Default_VRF_Extension_Universal" + }, + "operStatus": "HEALTHY", + "provisionMode": "DCNMTopDown", + "replicationMode": "Multicast", + "siteId": "65001", + "templateName": "Easy_Fabric", + "vrfExtensionTemplate": "Default_VRF_Extension_Universal", + "vrfTemplate": "Default_VRF_Universal" + } + ], + "MESSAGE": "OK", + "METHOD": "GET", + "REQUEST_PATH": "https://172.22.150.244:443/appcenter/cisco/ndfc/api/v1/rest/control/fabrics", + "RETURN_CODE": 200 } } diff --git a/tests/unit/modules/dcnm/dcnm_fabric/fixtures/responses_FabricSummary.json b/tests/unit/modules/dcnm/dcnm_fabric/fixtures/responses_FabricSummary.json index 21c0d52a8..cc44c89b5 100644 --- a/tests/unit/modules/dcnm/dcnm_fabric/fixtures/responses_FabricSummary.json +++ b/tests/unit/modules/dcnm/dcnm_fabric/fixtures/responses_FabricSummary.json @@ -237,5 +237,34 @@ "METHOD": "GET", "REQUEST_PATH": "https://172.22.150.244:443/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/switches/f1/overview", "RETURN_CODE": 404 + }, + "test_fabric_update_bulk_00130a": { + "DATA": { + "switchSWVersions": { + "10.2(5)": 2, + "10.3(1)": 2 + }, + "switchHealth": { + "Healthy": 1, + "Minor": 3 + }, + "switchHWVersions": { + "N9K-C93180YC-EX": 2, + "N9K-C9336C-FX2": 1, + "N9K-C9504": 1 + }, + "switchConfig": { + "NA": 4 + }, + "switchRoles": { + "leaf": 2, + "spine": 1, + "border gateway": 1 + } + }, + "MESSAGE": "OK", + "METHOD": "GET", + "REQUEST_PATH": "https://172.22.150.244:443/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/switches/f1/overview", + "RETURN_CODE": 200 } } diff --git a/tests/unit/modules/dcnm/dcnm_fabric/test_fabric_update_bulk.py b/tests/unit/modules/dcnm/dcnm_fabric/test_fabric_update_bulk.py index 48bc6d556..4c82aee40 100644 --- a/tests/unit/modules/dcnm/dcnm_fabric/test_fabric_update_bulk.py +++ b/tests/unit/modules/dcnm/dcnm_fabric/test_fabric_update_bulk.py @@ -1332,7 +1332,7 @@ def fabric_name(self): @fabric_name.setter def fabric_name(self, value): - raise ValueError("mocked exception") + raise ValueError("raised ApiEndpoints.fabric_name exception.") PATCH_API_ENDPOINTS = "ansible_collections.cisco.dcnm.plugins." PATCH_API_ENDPOINTS += "module_utils.fabric.endpoints.ApiEndpoints.fabric_name" @@ -1344,7 +1344,7 @@ def fabric_name(self, value): instance._fabrics_to_config_deploy = ["f1"] instance.config_save_result = {"f1": True} - match = "mocked exception" + match = r"raised ApiEndpoints\.fabric_name exception\." with pytest.raises(ValueError, match=match): fabric_update_bulk._config_deploy() @@ -1382,7 +1382,7 @@ def fabric_name(self): @fabric_name.setter def fabric_name(self, value): - raise ValueError("mocked exception") + raise ValueError("raised FabricSummary.fabric_name exception.") PATCH_API_ENDPOINTS = "ansible_collections.cisco.dcnm.plugins." PATCH_API_ENDPOINTS += ( @@ -1393,7 +1393,7 @@ def fabric_name(self, value): instance = fabric_update_bulk monkeypatch.setattr(instance, "fabric_summary", MockFabricSummary()) - match = "mocked exception" + match = r"raised FabricSummary\.fabric_name exception\." with pytest.raises(ValueError, match=match): fabric_update_bulk._can_fabric_be_deployed("f1") @@ -1475,7 +1475,8 @@ def mock_fixup_payloads_to_commit() -> None: Mock the FabricUpdateCommon._fixup_payloads_to_commit() to raise ``ValueError``. """ - raise ValueError("mocked exception.") + msg = "raised FabricUpdateCommon._fixup_payloads_to_commit exception." + raise ValueError(msg) PATCH = "ansible_collections.cisco.dcnm.plugins." PATCH += "module_utils.fabric.fabric_common.FabricCommon._fixup_payloads_to_commit" @@ -1497,7 +1498,7 @@ def mock_fixup_payloads_to_commit() -> None: instance, "_fixup_payloads_to_commit", mock_fixup_payloads_to_commit ) - match = r"mocked exception\." + match = r"raised FabricUpdateCommon\._fixup_payloads_to_commit exception\." with pytest.raises(ValueError, match=match): instance._send_payloads() @@ -1523,14 +1524,14 @@ def test_fabric_update_bulk_00120(monkeypatch, fabric_update_bulk) -> None: raise ``ValueError``. - Monkeypatch FabricCommon()._send_payload() to the mocked method. - Populate FabricUpdateCommon._payloads_to_commit with a payload - which contains an valid payload. + which contains a valid payload. """ def mock_send_payload(payload) -> None: """ Mock the FabricCommon()._send_payload() ``ValueError``. """ - raise ValueError("mocked exception.") + raise ValueError("raised FabricCommon.self_payload exception.") PATCH = "ansible_collections.cisco.dcnm.plugins." PATCH += "module_utils.fabric.fabric_common.FabricCommon._send_payload" @@ -1543,8 +1544,7 @@ def mock_send_payload(payload) -> None: "BGP_AS": "65001", "DEPLOY": "true", "FABRIC_NAME": "f1", - "FABRIC_TYPE": "VXLAN_EVPN", - "INVALID_KEY": True, + "FABRIC_TYPE": "VXLAN_EVPN" } ] @@ -1552,6 +1552,85 @@ def mock_send_payload(payload) -> None: instance, "_send_payload", mock_send_payload ) - match = r"mocked exception\." + match = r"raised FabricCommon\.self_payload exception\." + with pytest.raises(ValueError, match=match): + instance._send_payloads() + + +def test_fabric_update_bulk_00130(monkeypatch, fabric_update_bulk) -> None: + """ + Classes and Methods + - FabricCommon() + - __init__() + - _fixup_payloads_to_commit() + - FabricUpdateCommon() + - __init__() + - _send_payloads() + + + Summary + - Verify FabricUpdateCommon()._send_payloads() catches and + re-raises ``ValueError`` raised by + FabricCommon()._config_save() + + Setup + - Mock FabricCommon()._config_save() method to + raise ``ValueError``. + - Monkeypatch FabricCommon()._config_save() to the mocked method. + - Populate FabricUpdateCommon._payloads_to_commit with a payload + which contains a valid payload. + """ + method_name = inspect.stack()[0][3] + key = f"{method_name}a" + + def mock_config_save() -> None: + """ + Mock FabricCommon()._config_save() ``ValueError``. + """ + raise ValueError("raised FabricCommon.config_save exception.") + + PATCH_DCNM_SEND = "ansible_collections.cisco.dcnm.plugins." + PATCH_DCNM_SEND += "module_utils.common.rest_send.dcnm_send" + + def responses(): + yield responses_fabric_details_by_name(key) + yield responses_fabric_summary(key) + yield responses_fabric_update_bulk(key) + + gen = ResponseGenerator(responses()) + + def mock_dcnm_send(*args, **kwargs): + item = gen.next + return item + + with does_not_raise(): + instance = fabric_update_bulk + instance.fabric_details = FabricDetailsByName(params) + instance.fabric_details.rest_send = RestSend(MockAnsibleModule()) + instance.fabric_details.rest_send.unit_test = True + + instance.fabric_summary = FabricSummary(params) + instance.fabric_summary.rest_send = RestSend(MockAnsibleModule()) + instance.fabric_summary.rest_send.unit_test = True + + instance.rest_send = RestSend(MockAnsibleModule()) + instance.results = Results() + instance._payloads_to_commit = [ + { + "BGP_AS": "65001", + "DEPLOY": "true", + "FABRIC_NAME": "f1", + "FABRIC_TYPE": "VXLAN_EVPN", + "DEPLOY": "true" + } + ] + + monkeypatch.setattr(PATCH_DCNM_SEND, mock_dcnm_send) + + monkeypatch.setattr( + instance, "_config_save", mock_config_save + ) + + match = r"raised FabricCommon\.config_save exception\." with pytest.raises(ValueError, match=match): instance._send_payloads()