-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactored AWSUtilities to allow dependency injection for test cases
- Loading branch information
1 parent
6cde192
commit a8b0275
Showing
8 changed files
with
302 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
using Amazon.Runtime.CredentialManagement; | ||
using Amazon.Runtime; | ||
using System.Collections.Generic; | ||
|
||
namespace AWS.Deploy.CLI | ||
{ | ||
public class CredentialProfileStoreChainWrapper : ICredentialProfileStoreChain | ||
{ | ||
private readonly CredentialProfileStoreChain _chain = new CredentialProfileStoreChain(); | ||
|
||
public bool TryGetAWSCredentials(string profileName, out AWSCredentials credentials) | ||
=> _chain.TryGetAWSCredentials(profileName, out credentials); | ||
|
||
public bool TryGetProfile(string profileName, out CredentialProfile profile) | ||
=> _chain.TryGetProfile(profileName, out profile); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
using Amazon.Runtime.CredentialManagement; | ||
using Amazon.Runtime; | ||
using System.Collections.Generic; | ||
|
||
namespace AWS.Deploy.CLI | ||
{ | ||
public class FallbackCredentialsFactoryWrapper : IFallbackCredentialsFactory | ||
{ | ||
public AWSCredentials GetCredentials() => FallbackCredentialsFactory.GetCredentials(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
using Amazon.Runtime.CredentialManagement; | ||
using Amazon.Runtime; | ||
using System.Collections.Generic; | ||
|
||
namespace AWS.Deploy.CLI | ||
{ | ||
public interface ICredentialProfileStoreChain | ||
{ | ||
bool TryGetAWSCredentials(string profileName, out AWSCredentials credentials); | ||
bool TryGetProfile(string profileName, out CredentialProfile profile); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
using Amazon.Runtime; | ||
|
||
namespace AWS.Deploy.CLI | ||
{ | ||
public interface IFallbackCredentialsFactory | ||
{ | ||
AWSCredentials GetCredentials(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
using System.Collections.Generic; | ||
|
||
namespace AWS.Deploy.CLI | ||
{ | ||
public interface ISharedCredentialsFile | ||
{ | ||
List<string> ListProfileNames(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
using Amazon.Runtime.CredentialManagement; | ||
using Amazon.Runtime; | ||
using System.Collections.Generic; | ||
|
||
namespace AWS.Deploy.CLI | ||
{ | ||
public class SharedCredentialsFileWrapper : ISharedCredentialsFile | ||
{ | ||
private readonly SharedCredentialsFile _sharedCredentialsFile = new SharedCredentialsFile(); | ||
|
||
public List<string> ListProfileNames() => _sharedCredentialsFile.ListProfileNames(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,199 @@ | ||
using Amazon.Runtime.CredentialManagement; | ||
using Amazon.Runtime; | ||
using AWS.Deploy.CLI.Common.UnitTests.IO; | ||
using AWS.Deploy.Common.IO; | ||
using AWS.Deploy.Common.Recipes; | ||
using Moq; | ||
using System; | ||
using Xunit; | ||
using System.Threading.Tasks; | ||
using Amazon; | ||
using System.Linq; | ||
using System.Collections.Generic; | ||
|
||
namespace AWS.Deploy.CLI.UnitTests | ||
{ | ||
public class AWSUtilitiesTests | ||
{ | ||
private readonly IDirectoryManager _directoryManager; | ||
private readonly IOptionSettingHandler _optionSettingHandler; | ||
private readonly Mock<IToolInteractiveService> _mockToolInteractiveService; | ||
private readonly Mock<IConsoleUtilities> _mockConsoleUtilities; | ||
private readonly Mock<IServiceProvider> _mockServiceProvider; | ||
private readonly Mock<ICredentialProfileStoreChain> _mockCredentialProfileStoreChain; | ||
private readonly Mock<ISharedCredentialsFile> _mockSharedCredentialsFile; | ||
private readonly Mock<IFallbackCredentialsFactory> _mockFallbackCredentialsFactory; | ||
|
||
public AWSUtilitiesTests() | ||
{ | ||
_directoryManager = new TestDirectoryManager(); | ||
_mockToolInteractiveService = new Mock<IToolInteractiveService>(); | ||
_mockConsoleUtilities = new Mock<IConsoleUtilities>(); | ||
_mockServiceProvider = new Mock<IServiceProvider>(); | ||
_optionSettingHandler = new Mock<IOptionSettingHandler>().Object; | ||
_mockCredentialProfileStoreChain = new Mock<ICredentialProfileStoreChain>(); | ||
_mockSharedCredentialsFile = new Mock<ISharedCredentialsFile>(); | ||
_mockFallbackCredentialsFactory = new Mock<IFallbackCredentialsFactory>(); | ||
} | ||
|
||
private AWSUtilities CreateAWSUtilities() | ||
{ | ||
return new AWSUtilities( | ||
_mockServiceProvider.Object, | ||
_mockToolInteractiveService.Object, | ||
_mockConsoleUtilities.Object, | ||
_directoryManager, | ||
_optionSettingHandler, | ||
() => _mockCredentialProfileStoreChain.Object, | ||
() => _mockSharedCredentialsFile.Object, | ||
_mockFallbackCredentialsFactory.Object | ||
); | ||
} | ||
|
||
delegate void CredentialsCallback(string profileName, out AWSCredentials credentials); | ||
delegate bool CredentialsReturns(string profileName, out AWSCredentials credentials); | ||
|
||
delegate void ProfileCallback(string profileName, out CredentialProfile profile); | ||
delegate bool ProfileReturns(string profileName, out CredentialProfile profile); | ||
|
||
[Fact] | ||
public async Task ResolveAWSCredentials_WithValidProfileName_ReturnsCredentials() | ||
{ | ||
// Arrange | ||
var awsUtilities = CreateAWSUtilities(); | ||
var profileName = "valid-profile"; | ||
var mockCredentials = new Mock<AWSCredentials>(); | ||
var mockProfile = new CredentialProfile("valid-profile", new CredentialProfileOptions()) | ||
{ | ||
Region = RegionEndpoint.USEast1 | ||
}; | ||
|
||
_mockCredentialProfileStoreChain | ||
.Setup(c => c.TryGetAWSCredentials(It.IsAny<string>(), out It.Ref<AWSCredentials>.IsAny)) | ||
.Callback(new CredentialsCallback((string name, out AWSCredentials creds) => | ||
{ | ||
creds = mockCredentials.Object; | ||
})) | ||
.Returns(new CredentialsReturns((string name, out AWSCredentials creds) => | ||
{ | ||
creds = mockCredentials.Object; | ||
return true; | ||
})); | ||
|
||
_mockCredentialProfileStoreChain | ||
.Setup(c => c.TryGetProfile(It.IsAny<string>(), out It.Ref<CredentialProfile>.IsAny)) | ||
.Callback(new ProfileCallback((string name, out CredentialProfile profile) => | ||
{ | ||
profile = mockProfile; | ||
})) | ||
.Returns(new ProfileReturns((string name, out CredentialProfile profile) => | ||
{ | ||
profile = mockProfile; | ||
return true; | ||
})); | ||
|
||
// Act | ||
var result = await awsUtilities.ResolveAWSCredentials(profileName); | ||
|
||
// Assert | ||
Assert.NotNull(result); | ||
Assert.Equal(mockCredentials.Object, result.Item1); | ||
Assert.Equal("us-east-1", result.Item2); | ||
} | ||
|
||
[Fact] | ||
public async Task ResolveAWSCredentials_WithInvalidProfileName_ThrowsException() | ||
{ | ||
// Arrange | ||
var awsUtilities = CreateAWSUtilities(); | ||
var profileName = "invalid-profile"; | ||
|
||
_mockCredentialProfileStoreChain | ||
.Setup(c => c.TryGetAWSCredentials(It.IsAny<string>(), out It.Ref<AWSCredentials>.IsAny)) | ||
.Returns(false); | ||
|
||
// Act & Assert | ||
await Assert.ThrowsAsync<FailedToGetCredentialsForProfile>(() => awsUtilities.ResolveAWSCredentials(profileName)); | ||
} | ||
|
||
[Fact] | ||
public async Task ResolveAWSCredentials_WithNullProfileName_UsesFallbackCredentials() | ||
{ | ||
// Arrange | ||
var awsUtilities = CreateAWSUtilities(); | ||
var mockFallbackCredentials = new Mock<AWSCredentials>(); | ||
|
||
_mockFallbackCredentialsFactory | ||
.Setup(f => f.GetCredentials()) | ||
.Returns(mockFallbackCredentials.Object); | ||
|
||
// Act | ||
var result = await awsUtilities.ResolveAWSCredentials(null); | ||
|
||
// Assert | ||
Assert.NotNull(result); | ||
Assert.Equal(mockFallbackCredentials.Object, result.Item1); | ||
Assert.Null(result.Item2); | ||
} | ||
|
||
[Fact] | ||
public async Task ResolveAWSCredentials_WithNoCredentials_PromptsUserToChooseProfile() | ||
{ | ||
// Arrange | ||
var awsUtilities = CreateAWSUtilities(); | ||
var profileNames = new List<string> { "profile1", "profile2" }; | ||
var selectedProfileName = "profile1"; | ||
var mockCredentials = new Mock<AWSCredentials>(); | ||
var mockProfile = new CredentialProfile(selectedProfileName, new CredentialProfileOptions()) | ||
{ | ||
Region = RegionEndpoint.USEast2 | ||
}; | ||
|
||
_mockFallbackCredentialsFactory | ||
.Setup(f => f.GetCredentials()) | ||
.Throws(new AmazonServiceException("No credentials found")); | ||
|
||
_mockSharedCredentialsFile | ||
.Setup(s => s.ListProfileNames()) | ||
.Returns(profileNames); | ||
|
||
_mockConsoleUtilities | ||
.Setup(c => c.AskUserToChoose( | ||
It.Is<List<string>>(list => list.SequenceEqual(profileNames)), | ||
It.Is<string>(s => s == "Select AWS Credentials Profile"), | ||
It.IsAny<string>(), | ||
It.IsAny<string>() | ||
)) | ||
.Returns(selectedProfileName); | ||
|
||
|
||
|
||
_mockCredentialProfileStoreChain | ||
.Setup(c => c.TryGetAWSCredentials(It.IsAny<string>(), out It.Ref<AWSCredentials>.IsAny)) | ||
.Returns(new CredentialsReturns((string name, out AWSCredentials creds) => | ||
{ | ||
creds = mockCredentials.Object; | ||
return true; | ||
})); | ||
|
||
_mockCredentialProfileStoreChain | ||
.Setup(c => c.TryGetProfile(It.IsAny<string>(), out It.Ref<CredentialProfile>.IsAny)) | ||
.Returns(new ProfileReturns((string name, out CredentialProfile profile) => | ||
{ | ||
profile = mockProfile; | ||
return true; | ||
})); | ||
|
||
// Act | ||
var result = await awsUtilities.ResolveAWSCredentials(null); | ||
|
||
// Assert | ||
Assert.NotNull(result); | ||
Assert.Equal(mockCredentials.Object, result.Item1); | ||
Assert.Equal("us-east-2", result.Item2); | ||
_mockConsoleUtilities.Verify(c => c.AskUserToChoose(It.IsAny<List<string>>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()), Times.Once); | ||
} | ||
|
||
} | ||
|
||
} |