examples
examples copied to clipboard
Add more examples for AzureNative C# UniteTesting.
I'm trying to write a unit test for AzureFunction provisioning. I've started with the code from this repository, and I'm using this snippet to retrieve Storage keys:
private static Output<string> GetConnectionString(Input<string> resourceGroupName, Input<string> accountName) {
// Retrieve the primary storage account key.
Output<ListStorageAccountKeysResult> storageAccountKeys = Output.All<string>(resourceGroupName, accountName).Apply(t => {
var resourceGroupName = t[0];
var accountName = t[1];
return ListStorageAccountKeys.InvokeAsync(
new ListStorageAccountKeysArgs {
ResourceGroupName = resourceGroupName,
AccountName = accountName
});
});
return storageAccountKeys.Apply(keys => {
var primaryStorageKey = keys.Keys[0].Value;
// Build the connection string to the storage account.
return Output.Format($"DefaultEndpointsProtocol=https;AccountName={accountName};AccountKey={primaryStorageKey}");
});
}
It's clear to me what this code is doing.
When I run my tests (a very basic one), this snippet fails, because it cannot construct ListStorageAccountKeysResult
object, hence there is nothing in keys.Keys
ImmutableArray.
The actual unit test is not very relevant, it's pretty much a copy-past of the existing example from this repository with all the clutter removed:
[Fact]
public async Task Stack_Creation_Does_Not_Fail() {
try {
var resources = await Testing.RunAsync<MyStack>();
resources.IsEmpty.ShouldBeFalse();
}
catch (Exception ex) {
_testOutputHelper.WriteLine($"{ex.Message}: {ex}");
throw new XunitException($"Stack creation should not fail, {ex}");
}
}
Now I want to write a set of unit tests for it, however I don't understand how to mock the call to ListStorageAccountKeys
What I have so far is:
internal class Moks : IMock{
//public Task<(string? id, object state)> NewResourceAsync(MockResourceArgs args) { ...}
#pragma warning disable 1998
public async Task<object> CallAsync(MockCallArgs args) {
#pragma warning restore 1998
var outputs = ImmutableDictionary.CreateBuilder<string, object>();
outputs.AddRange(args.Args);
if (args.Token == "azure-native:authorization:getClientConfig") {
outputs.Add("ClientId", Guid.NewGuid().ToString());
outputs.Add("ObjectId", Guid.NewGuid().ToString());
outputs.Add("SubscriptionId", Guid.NewGuid().ToString());
outputs.Add("TenantId", Guid.NewGuid().ToString());
return outputs;
}
if (args.Token == "azure-native:storage:listStorageAccountKeys") {
// HOW DO I FORMAT StorageAccountKeyResponse HERE?
return outputs;
};
}
return outputs;
}}
I would appreciate to have either more examples covering basic steps like this one. Perhaps you should add a set of unit tests for each example stack in this repo? This would be a great start.
And of course I'd like to solve my current problem. Can anyone show me how do I mock this request?
Affected feature
Pulumi.AzureNative testing.
I am also having this issue. the ListStorageAccountKeysResult and StorageAccountKeyResponse classes aren't mockable. what other options are there for testing this?
I am also having the same issue. Trying the automate a secret provisioning with pulumi. By using the created storage account key as the value for the secret. and failing due to this is not mocked.. any options to solve this.. ?
@asizikov @shamali86 @pete-lembke-relativity , I am also facing this problem: I am not able to mock the StorageAccountKeyResponse. Were you able to manage this issue or it is still without proper solution?
Yes @erickroseira, @asizikov @pete-lembke-relativity, was able to solve this with a workaround. What's happening is with Async the resources are being mocked and tested. But when we try to call the storage account key it is returned null. As a workaround I use a try catch to pass a string at the time of the mock and test as below:
private static async Task<string> GetStorageAccountPrimaryKey(string resourceGroupName, string accountName)
{
try{
var accountKeys = await ListStorageAccountKeys.InvokeAsync(new ListStorageAccountKeysArgs
{
AccountName = accountName,
ResourceGroupName = resourceGroupName
});
return accountKeys.Keys[0].Value;
}
catch{
Console.WriteLine("ABCKeyName");
}
return string.Empty;
}
Hope this try catch can solve your issue too.. Let me know the outcome..
@shamali86 @pete-lembke-relativity @asizikov . Thank you by providing us your workaround solution. After struggling a little bit with a coworker of mine, we were able to find a proper solution:
public Task<object> CallAsync(MockCallArgs args)
{
var outputs = ImmutableDictionary.CreateBuilder<string, object>();
outputs.AddRange(args.Args);
if (args.Token == "azure:keyvault/getKeyVault:getKeyVault")
{
outputs.Add("id", Guid.NewGuid().ToString());
}
// SOLUTION GOES HERE
if (args.Token == "azure-native:storage:listStorageAccountKeys")
{
var json = JsonDocument.Parse("[{\"value\":\"valueKeyStorage\"}]").RootElement;
outputs.Add("keys", json);
}
return Task.FromResult((object)outputs);
}
The point is: looking into the Pulumi SDK test code we have discovered that is possible to send a JsonElement specifying the object structure that you intend to mock, in this case StorageAccountKeyResponse class' structure.
Since we were interested in mocking the field 'Value' (of StorageAccountKeyResponse class), we have defined the JsonElement only with this property.
I hope this can help you as well. Thanks.
After two days of searching for examples and asking on Slack, I finally came across this GitHub issue buried on page 3 of my search results, and it's really disappointing to find, again, that the API in dotnet is "write JSON" 😕 Props to @erickroseira and your colleague for figuring this out!
I really hope this area gets some attention in the near future...
@alastairs thanks for linking these two issues together!