Skip to content

Commit bd57ff3

Browse files
committed
feat(extensions)!: migrate AwsClientFactoryWrapper to AWS SDK v4
BREAKING CHANGE: Extensions package now requires AWS SDK v4 - Replace non-generic ClientFactory with ClientFactory<T> - Update constructor to use AWSOptions-only signature - Fix method resolution for CreateServiceClient(IServiceProvider) - Add comprehensive error handling tests - Remove AWS SDK v3 compatibility layer Resolves Extensions test failures blocking v2.0.0-preview1 release. All 38 Extensions tests now passing.
1 parent 6f5cea3 commit bd57ff3

File tree

2 files changed

+38
-20
lines changed

2 files changed

+38
-20
lines changed

src/LocalStack.Client.Extensions/AwsClientFactoryWrapper.cs

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,39 +5,36 @@ namespace LocalStack.Client.Extensions;
55

66
public sealed class AwsClientFactoryWrapper : IAwsClientFactoryWrapper
77
{
8-
private static readonly string ClientFactoryFullName = "Amazon.Extensions.NETCore.Setup.ClientFactory";
8+
private static readonly string ClientFactoryGenericTypeName = "Amazon.Extensions.NETCore.Setup.ClientFactory`1";
99
private static readonly string CreateServiceClientMethodName = "CreateServiceClient";
1010

1111
public AmazonServiceClient CreateServiceClient<TClient>(IServiceProvider provider, AWSOptions? awsOptions) where TClient : IAmazonService
1212
{
13-
Type? clientFactoryType = typeof(ConfigurationException).Assembly.GetType(ClientFactoryFullName);
13+
Type? genericFactoryType = typeof(ConfigurationException).Assembly.GetType(ClientFactoryGenericTypeName);
1414

15-
if (clientFactoryType == null)
15+
if (genericFactoryType == null)
1616
{
17-
throw new LocalStackClientConfigurationException($"Failed to find internal ClientFactory in {ClientFactoryFullName}");
17+
throw new LocalStackClientConfigurationException($"Failed to find internal ClientFactory<T> in {ClientFactoryGenericTypeName}");
1818
}
1919

20-
ConstructorInfo? constructorInfo =
21-
clientFactoryType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(Type), typeof(AWSOptions) }, null);
20+
// Create ClientFactory<TClient>
21+
Type concreteFactoryType = genericFactoryType.MakeGenericType(typeof(TClient));
22+
ConstructorInfo? constructor = concreteFactoryType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(AWSOptions) }, null);
2223

23-
if (constructorInfo == null)
24+
if (constructor == null)
2425
{
25-
throw new LocalStackClientConfigurationException("ClientFactory missing a constructor with parameters Type and AWSOptions.");
26+
throw new LocalStackClientConfigurationException("ClientFactory<T> missing constructor with AWSOptions parameter.");
2627
}
2728

28-
Type clientType = typeof(TClient);
29+
object factory = constructor.Invoke(new object[] { awsOptions! });
30+
MethodInfo? createMethod = factory.GetType().GetMethod(CreateServiceClientMethodName, BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(IServiceProvider) }, null);
2931

30-
object clientFactory = constructorInfo.Invoke(new object[] { clientType, awsOptions! });
31-
32-
MethodInfo? methodInfo = clientFactory.GetType().GetMethod(CreateServiceClientMethodName, BindingFlags.NonPublic | BindingFlags.Instance);
33-
34-
if (methodInfo == null)
32+
if (createMethod == null)
3533
{
36-
throw new LocalStackClientConfigurationException($"Failed to find internal method {CreateServiceClientMethodName} in {ClientFactoryFullName}");
34+
throw new LocalStackClientConfigurationException($"ClientFactory<T> missing {CreateServiceClientMethodName}(IServiceProvider) method.");
3735
}
3836

39-
object serviceInstance = methodInfo.Invoke(clientFactory, new object[] { provider });
40-
37+
object serviceInstance = createMethod.Invoke(factory, new object[] { provider });
4138
return (AmazonServiceClient)serviceInstance;
4239
}
4340
}

tests/LocalStack.Client.Extensions.Tests/AwsClientFactoryWrapperTests.cs

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,40 @@ public void CreateServiceClient_Should_Throw_LocalStackClientConfigurationExcept
1919
Type type = _awsClientFactoryWrapper.GetType();
2020
const BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Static;
2121

22-
FieldInfo? clientFactoryFullNameField = type.GetField("ClientFactoryFullName", bindingFlags);
22+
FieldInfo? clientFactoryGenericTypeNameField = type.GetField("ClientFactoryGenericTypeName", bindingFlags);
2323
FieldInfo? createServiceClientMethodNameFieldInfo = type.GetField("CreateServiceClientMethodName", bindingFlags);
2424

25-
Assert.NotNull(clientFactoryFullNameField);
25+
Assert.NotNull(clientFactoryGenericTypeNameField);
2626
Assert.NotNull(createServiceClientMethodNameFieldInfo);
2727

28-
SetPrivateReadonlyField(clientFactoryFullNameField, "NonExistingType");
28+
SetPrivateReadonlyField(clientFactoryGenericTypeNameField, "NonExistingType");
2929
SetPrivateReadonlyField(createServiceClientMethodNameFieldInfo, "NonExistingMethod");
3030

3131
Assert.Throws<LocalStackClientConfigurationException>(
3232
() => _awsClientFactoryWrapper.CreateServiceClient<MockAmazonServiceClient>(_mockServiceProvider.Object, _awsOptions));
3333
}
3434

35+
[Fact]
36+
public void CreateServiceClient_Should_Throw_LocalStackClientConfigurationException_When_ClientFactory_Type_Not_Found()
37+
{
38+
Type type = _awsClientFactoryWrapper.GetType();
39+
const BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Static;
40+
41+
FieldInfo? clientFactoryGenericTypeNameField = type.GetField("ClientFactoryGenericTypeName", bindingFlags);
42+
FieldInfo? createServiceClientMethodNameFieldInfo = type.GetField("CreateServiceClientMethodName", bindingFlags);
43+
44+
Assert.NotNull(clientFactoryGenericTypeNameField);
45+
Assert.NotNull(createServiceClientMethodNameFieldInfo);
46+
47+
SetPrivateReadonlyField(clientFactoryGenericTypeNameField, "NonExistingType");
48+
SetPrivateReadonlyField(createServiceClientMethodNameFieldInfo, "NonExistingMethod");
49+
50+
var exception = Assert.Throws<LocalStackClientConfigurationException>(
51+
() => _awsClientFactoryWrapper.CreateServiceClient<MockAmazonServiceClient>(_mockServiceProvider.Object, _awsOptions));
52+
53+
Assert.Contains("Failed to find AWS SDK v4 ClientFactory<T>", exception.Message, StringComparison.Ordinal);
54+
}
55+
3556
[Fact]
3657
public void CreateServiceClient_Should_Create_Client_When_UseLocalStack_False()
3758
{

0 commit comments

Comments
 (0)