I have a solution in .NET 5 with some Unit Tests in NUnit that required some secrets to work correctly. Testing in Visual Studio using local user secrets works fine but now I want to try to integrate using Azure Key Vault and run the Unit Tests inside a Pipeline.
I added the Task AzureKeyVault@2
and according to the log the secrets are downloaded just fine but in the next steps, the Unit Tests fail because it doesn't find some keys when try to access from IConfiguration
.
This is my azure-pipelines.yml
(only the relevant parts).
- job: Init
displayName: Unit Testing
variables:
solutionToBuild: 'Solution.sln'
unitTestsProject: 'UnitTests\UnitTests.csproj'
buildConfiguration: 'Release'
steps:
- task: DotNetCoreCLI@2
displayName: 'Restore Packages'
inputs:
command: 'restore'
projects: '$(solutionToBuild)'
verbosityRestore: minimal
feedsToUse: 'select'
- task: DotNetCoreCLI@2
displayName: 'Build Solution'
inputs:
command: 'build'
projects: '$(solutionToBuild)'
arguments: '-c $(buildConfiguration)'
- task: AzureKeyVault@2
displayName: 'Configure Key Vault'
inputs:
azureSubscription: '**-etc-**'
KeyVaultName: '**key-vault-name**'
- task: DotNetCoreCLI@2
displayName: 'Run Unit Tests'
inputs:
command: 'test'
projects: '$(unitTestsProject)'
arguments: '-c $(buildConfiguration) --collect:"XPlat Code Coverage"'
publishTestResults: true
I created this basic tests that are currently failing in the Pipeline. I'm using the Host.CreateDefaultBuilder()
method to initialize all the unit tests.
[Test]
[TestCase("secret-key-1")]
[TestCase("secret-key-1")]
public void TestSecrets(string key)
{
Assert.NotNull(_config[key]);
Assert.IsNotEmpty(_config[key]);
}
Does the AzureKeyVault@2
pass the secrets keys and values for the DotNetCoreCLI@2
task or do I need an additional step?. I read that you can play with the FileTransform@1 step using an empty appsettings.json
but I couldn't make it work. Is there a correct method to achieve this?
I finally made it work. I decided to go to the route of the appsettings.json
. with File Transformation Task. I will answer myself just in case anyone else find this useful.
You need to have a appsettings.json
in your Unit Test project, and add all the required keys you'll need in your Unit Tests, but without values, only ""
, e.g.
{
"secret-key-1": "",
"secret-key-2": "",
"secret-key-3": "",
}
If you want to test locally you can use the local user-secrets option in Visual Studio and add all the keys like in your appsettings.json
file but with actual values (you'll be the only one to view the values anyways)
{
"secret-key-1": "some-secret-value",
"secret-key-2": "some-secret-value",
"secret-key-3": "some-secret-value",
}
Then, in your SetUp
method you can initialize the IConfiguration
class as follow. (You can easily transform this into a static method if you have multiple Unit Tests classes)
[TestFixture]
public class MyUnitTest
private IConfiguration Config;
[SetUp]
public void Setup()
{
Config = new ConfigurationBuilder()
.SetBasePath(AppContext.BaseDirectory)
.AddJsonFile("appsettings.json", optional: true)
.AddUserSecrets(Assembly.GetExecutingAssembly())
.Build();
}
[Test]
[TestCase("secret-key-1")
[TestCase("secret-key-2")
public void TestKeys(string key)
{
Assert.NotNull(config[key]);
Assert.IsNotEmpty(config[key]);
}
}
Finally, in the azure-pipelines.yml
you add the FileTransform@1
Task after the AzureKeyVault@2
.
- task: AzureKeyVault@2
displayName: 'Configure Key Vault'
inputs:
azureSubscription: '**-etc-**'
KeyVaultName: '**key-vault-name**'
- task: FileTransform@1
displayName: 'Set Unit Tests Settings'
inputs:
folderPath: '$(projectsDirectory)'
fileType: 'json'
targetFiles: '**/appsettings.json'
- task: DotNetCoreCLI@2
displayName: 'Run Unit Tests'
inputs:
command: 'test'
projects: '$(unitTestsProject)'
arguments: '-c $(buildConfiguration) --collect:"XPlat Code Coverage"'
publishTestResults: true
And that's it, after that in the pipeline log you'll see something like this in the FileTransform@1
task
Applying JSON variable substitution for **/appsettings.json
Applying JSON variable substitution for D:\a\1\s\UnitTests\appsettings.json
Substituting value on key secret-key-1 with (string) value: ***
Substituting value on key secret-key-2 with (string) value: ***
Substituting value on key secret-key-3 with (string) value: ***