如何Mock Azure Subscriptions - List Locations实现物理地域获取方法
实现带Mock的Azure物理地域获取方法
一、实际调用Azure API的实现
依赖Azure官方管理库Azure.ResourceManager,通过ArmClient调用订阅地域列表接口,再过滤掉逻辑地域(如global)得到物理地域:
using Azure.ResourceManager; using Azure.ResourceManager.Resources; using System.Linq; using System.Threading; using System.Threading.Tasks; public class AzureRegionService { private readonly ArmClient _armClient; public AzureRegionService(ArmClient armClient) { _armClient = armClient; } public async Task<IEnumerable<Region>> GetPhysicalRegions(CancellationToken token = default) { var subscription = await _armClient.GetDefaultSubscriptionAsync(token); var locations = await subscription.GetLocationsAsync(token).ToListAsync(token); // 过滤物理地域:排除无物理位置的逻辑地域 return locations.Where(loc => !string.IsNullOrEmpty(loc.PhysicalLocation)) .Select(loc => new Region { Name = loc.Name, DisplayName = loc.DisplayName, PhysicalLocation = loc.PhysicalLocation }); } } // 定义Region实体类 public class Region { public string Name { get; set; } public string DisplayName { get; set; } public string PhysicalLocation { get; set; } }
二、Mock实现(单元测试场景)
根据测试需求,有两种Mock方式:
1. 直接Mock服务方法
适用于测试依赖GetPhysicalRegions的业务组件,用Moq快速模拟返回结果:
using Moq; using Xunit; public class BusinessServiceTests { [Fact] public async Task TestBusinessLogicWithMockedRegions() { // 准备模拟的物理地域数据 var mockedRegions = new List<Region> { new Region { Name = "eastus", DisplayName = "East US", PhysicalLocation = "United States" }, new Region { Name = "westeurope", DisplayName = "West Europe", PhysicalLocation = "Europe" } }; // 构建服务Mock实例 var regionServiceMock = new Mock<AzureRegionService>(MockBehavior.Loose, It.IsAny<ArmClient>()); regionServiceMock.Setup(s => s.GetPhysicalRegions(It.IsAny<CancellationToken>())) .ReturnsAsync(mockedRegions); // 注入Mock服务到业务组件并执行测试 var businessService = new SomeBusinessService(regionServiceMock.Object); var result = await businessService.DoSomethingWithRegions(); Assert.NotNull(result); Assert.Equal(2, result.Count()); } }
2. Mock Azure SDK依赖
适用于测试AzureRegionService本身的过滤逻辑,模拟Azure API的返回:
using Moq; using Azure.ResourceManager.Resources; using Azure.ResourceManager.Resources.Models; using Xunit; public class AzureRegionServiceTests { [Fact] public async Task GetPhysicalRegions_FiltersOutLogicalRegions() { // 模拟Azure返回的地域列表,包含物理和逻辑地域 var mockAzureLocations = new List<LocationData> { new LocationData { Name = "eastus", DisplayName = "East US", PhysicalLocation = "United States" }, new LocationData { Name = "westeurope", DisplayName = "West Europe", PhysicalLocation = "Europe" }, new LocationData { Name = "global", DisplayName = "Global", PhysicalLocation = null } }; // Mock LocationCollection的异步查询 var locationCollectionMock = new Mock<LocationCollection>(); locationCollectionMock.Setup(c => c.GetAllAsync(It.IsAny<CancellationToken>())) .ReturnsAsync(mockAzureLocations); // Mock SubscriptionResource var subscriptionMock = new Mock<SubscriptionResource>(); subscriptionMock.Setup(s => s.GetLocationsAsync(It.IsAny<CancellationToken>())) .Returns(locationCollectionMock.Object); // Mock ArmClient var armClientMock = new Mock<ArmClient>(); armClientMock.Setup(c => c.GetDefaultSubscriptionAsync(It.IsAny<CancellationToken>())) .ReturnsAsync(subscriptionMock.Object); // 实例化服务并调用方法 var regionService = new AzureRegionService(armClientMock.Object); var result = await regionService.GetPhysicalRegions(); // 验证结果:排除了逻辑地域global Assert.Equal(2, result.Count()); Assert.DoesNotContain(result, r => r.Name == "global"); } }
三、核心注意事项
- 逻辑地域过滤:Azure返回的地域包含逻辑类型(如
global、部分政府云专属地域),需通过PhysicalLocation是否非空来判断物理地域。 - SDK版本适配:示例使用最新的
Azure.ResourceManager(v1.x+),若使用旧版Microsoft.Azure.Management.ResourceManager,需调整为对应的SubscriptionClient.ListLocations()方法。 - Mock策略选择:业务测试优先直接Mock服务方法,服务层测试则Mock底层SDK依赖以验证逻辑正确性。
内容的提问来源于stack exchange,提问作者Stanislav
相关产品推荐
相关产品推荐

