Skip to content

Commit 0b4c65c

Browse files
[Azure Mgmt Generator] Skip generation of mockable resources without methods (#54137)
Co-authored-by: ArcturusZhang <[email protected]> Co-authored-by: copilot-swe-agent[bot] <[email protected]>
1 parent a6d60d2 commit 0b4c65c

File tree

4 files changed

+66
-8
lines changed

4 files changed

+66
-8
lines changed

eng/packages/http-client-csharp-mgmt/generator/Azure.Generator.Management/src/ManagementOutputLibrary.cs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -138,20 +138,28 @@ _mockableResources is not null ||
138138
resourceDict,
139139
resourceMethodCategories,
140140
ManagementClientGenerator.Instance.InputLibrary.NonResourceMethods);
141-
var mockableArmClientResource = new MockableArmClientProvider(_resources);
141+
var mockableArmClientResource = MockableArmClientProvider.TryCreate(_resources);
142142
var mockableResources = new Dictionary<ResourceScope, MockableResourceProvider>(resourcesAndMethodsPerScope.Count);
143143
foreach (var (scope, (resourcesInScope, resourceMethods, nonResourceMethods)) in resourcesAndMethodsPerScope)
144144
{
145-
if (scope != ResourceScope.Extension &&
146-
(resourcesInScope.Count > 0 || resourceMethods.Count > 0 || nonResourceMethods.Count > 0))
145+
if (scope != ResourceScope.Extension)
147146
{
148-
var mockableExtension = new MockableResourceProvider(scope, resourcesInScope, resourceMethods, nonResourceMethods);
149-
mockableResources.Add(scope, mockableExtension);
147+
var mockableExtension = MockableResourceProvider.TryCreate(scope, resourcesInScope, resourceMethods, nonResourceMethods);
148+
if (mockableExtension != null)
149+
{
150+
mockableResources.Add(scope, mockableExtension);
151+
}
150152
}
151153
}
152154

153155
_mockableResourcesByScopeDict = mockableResources;
154-
_mockableResources = [mockableArmClientResource, ..mockableResources.Values];
156+
var allMockableResources = new List<MockableResourceProvider>();
157+
if (mockableArmClientResource != null)
158+
{
159+
allMockableResources.Add(mockableArmClientResource);
160+
}
161+
allMockableResources.AddRange(mockableResources.Values);
162+
_mockableResources = allMockableResources;
155163
_extensionProvider = new ExtensionProvider(_mockableResources);
156164

157165
static Dictionary<ResourceScope, ResourcesAndNonResourceMethodsInScope> BuildResourcesAndNonResourceMethods(

eng/packages/http-client-csharp-mgmt/generator/Azure.Generator.Management/src/Providers/MockableArmClientProvider.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,25 @@ namespace Azure.Generator.Management.Providers
1717
internal sealed class MockableArmClientProvider : MockableResourceProvider
1818
{
1919
// TODO -- we also need to put operations here when we want to support scope resources/operations https://github.com/Azure/azure-sdk-for-net/issues/51821
20-
public MockableArmClientProvider(IReadOnlyList<ResourceClientProvider> resources)
20+
private MockableArmClientProvider(IReadOnlyList<ResourceClientProvider> resources)
2121
: base(typeof(ArmClient), RequestPathPattern.Tenant, resources, new Dictionary<ResourceClientProvider, IReadOnlyList<ResourceMethod>>(), [])
2222
{
2323
}
2424

25+
/// <summary>
26+
/// Creates a new instance of <see cref="MockableArmClientProvider"/> if there are resources to generate methods for.
27+
/// </summary>
28+
/// <param name="resources">The resources to generate methods for.</param>
29+
/// <returns>A new instance of <see cref="MockableArmClientProvider"/> if there are resources, otherwise null.</returns>
30+
public static MockableArmClientProvider? TryCreate(IReadOnlyList<ResourceClientProvider> resources)
31+
{
32+
if (resources.Count == 0)
33+
{
34+
return null;
35+
}
36+
return new MockableArmClientProvider(resources);
37+
}
38+
2539
protected override MethodProvider[] BuildMethods()
2640
{
2741
var methods = new List<MethodProvider>(_resources.Count);

eng/packages/http-client-csharp-mgmt/generator/Azure.Generator.Management/src/Providers/MockableResourceProvider.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,28 @@ internal class MockableResourceProvider : TypeProvider
3838
/// <param name="resources">the resources in this scope.</param>
3939
/// <param name="resourceMethods">the resource methods that belong to this scope.</param>
4040
/// <param name="nonResourceMethods">the non-resource methods that belong to this scope.</param>
41-
public MockableResourceProvider(ResourceScope resourceScope, IReadOnlyList<ResourceClientProvider> resources, IReadOnlyDictionary<ResourceClientProvider, IReadOnlyList<ResourceMethod>> resourceMethods, IReadOnlyList<NonResourceMethod> nonResourceMethods)
41+
private MockableResourceProvider(ResourceScope resourceScope, IReadOnlyList<ResourceClientProvider> resources, IReadOnlyDictionary<ResourceClientProvider, IReadOnlyList<ResourceMethod>> resourceMethods, IReadOnlyList<NonResourceMethod> nonResourceMethods)
4242
: this(ResourceHelpers.GetArmCoreTypeFromScope(resourceScope), RequestPathPattern.GetFromScope(resourceScope), resources, resourceMethods, nonResourceMethods)
4343
{
4444
}
4545

46+
/// <summary>
47+
/// Creates a new instance of <see cref="MockableResourceProvider"/> if there are resources or methods to generate.
48+
/// </summary>
49+
/// <param name="resourceScope">The scope of this mockable resource.</param>
50+
/// <param name="resources">The resources in this scope.</param>
51+
/// <param name="resourceMethods">The resource methods that belong to this scope.</param>
52+
/// <param name="nonResourceMethods">The non-resource methods that belong to this scope.</param>
53+
/// <returns>A new instance of <see cref="MockableResourceProvider"/> if there are resources or methods, otherwise null.</returns>
54+
public static MockableResourceProvider? TryCreate(ResourceScope resourceScope, IReadOnlyList<ResourceClientProvider> resources, IReadOnlyDictionary<ResourceClientProvider, IReadOnlyList<ResourceMethod>> resourceMethods, IReadOnlyList<NonResourceMethod> nonResourceMethods)
55+
{
56+
if (resources.Count == 0 && resourceMethods.Count == 0 && nonResourceMethods.Count == 0)
57+
{
58+
return null;
59+
}
60+
return new MockableResourceProvider(resourceScope, resources, resourceMethods, nonResourceMethods);
61+
}
62+
4663
private protected MockableResourceProvider(CSharpType armCoreType, RequestPathPattern contextualPath, IReadOnlyList<ResourceClientProvider> resources, IReadOnlyDictionary<ResourceClientProvider, IReadOnlyList<ResourceMethod>> resourceMethods, IReadOnlyList<NonResourceMethod> nonResourceMethods)
4764
{
4865
_resources = resources;

eng/packages/http-client-csharp-mgmt/generator/Azure.Generator.Management/test/Providers/ExtensionProviderTests.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,5 +70,24 @@ public void Verify_GetResourceByIdMethods()
7070
Assert.IsNotNull(getMethod);
7171
Assert.AreEqual(resource!.Type, getMethod!.Signature.ReturnType);
7272
}
73+
74+
[TestCase]
75+
public void Verify_MockableResourcesWithNoMethods_AreNotGenerated()
76+
{
77+
// Verify that all MockableResourceProvider instances in the output have at least one method
78+
// This ensures that mockable resources without methods are filtered out
79+
var mockableResources = _plugin.OutputLibrary.TypeProviders
80+
.OfType<MockableResourceProvider>().ToList();
81+
82+
// With resources defined, there should be mockable resources
83+
Assert.That(mockableResources.Count, Is.GreaterThan(0), "There should be at least one mockable resource when resources are defined");
84+
85+
// All mockable resources in the output should have at least one method
86+
foreach (var mockableResource in mockableResources)
87+
{
88+
Assert.That(mockableResource.Methods.Count, Is.GreaterThan(0),
89+
$"MockableResourceProvider '{mockableResource.Name}' should have at least one method to be included in the output.");
90+
}
91+
}
7392
}
7493
}

0 commit comments

Comments
 (0)