Pulumi Unit Testing

It has been a while since i wrote a blog. As promised, I re-visit Pulumi. Interestingly enough i am currently working on a project using Terraform. I really like Terraform, it is easy to structure and write code in.

Anyhow, let’s get stuck in.

Testing infrastructure

One of my bug bears with Terraform is to do testing you have to learn Go. Another language to learn!!! I know there are lots of testing suites out there but I just want to write unit tests in a plain old Object Oriented language like C#.

So given that Pulumi allows you to write IaC code in your language of choice why not give it a try.

Setup your unit tests

In my example, thanks to https://www.pulumi.com/blog/unit-testing-cloud-deployments-with-dotnet I created a Unit test (should be separate project) class to facilitate the tests.

As suggested by the Pulumi article i decided to install NUnit as my unit testing framework.

A Sample test

So i used the example above to create a sample test. As this is a unit test Pulumi allows you to inject Mocks to simulate interaction with Pulumi and the ARM API. In the below example I test for the existence of two tags.

namespace UnitTesting
{
    [TestFixture]
    public class StorageStackUnitTest
    {
        [Test]
        public async Task ResourceGroupShouldHaveEnvironmentTag()
        {
            var resources = await TestAsync();

            var resourceGroup = resources.OfType<ResourceGroup>().First();

            var tags = await resourceGroup.Tags.GetValueAsync();
            tags.Should().NotBeNull("Tags must be defined");
            tags.Should().ContainKey("Environment");
            tags.Should().ContainKey("Owner");
            tags.Should().HaveCount(2);
        }

        private static Task<ImmutableArray<Resource>> TestAsync()
        {
            return Deployment.TestAsync<StorageAccountStack>(new Mocks(), new TestOptions { IsPreview = false });
        }
    }
}

To run these tests run dotnet core:

At first I got the following error

 Error Message:
   Pulumi.RunException : Running program '/Users/dummy/.../pulumi-dotnetcore/azureiac/bin/Debug/netcoreapp3.1/testhost.dll' failed with an unhandled exception:
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
 ---> Pulumi.Config+ConfigMissingException: Missing Required configuration variable 'project:resourceGroupName'
	please set a value using the command `pulumi config set project:storageReplication <value>`

This was a bit baffling to start of with. Then i realised the Pulumi API does not allow you to mock the configuration set for the project. the project:resourceGroupName is the key value defined in my Pulumi config file:

config:
  azure:location: ukwest
  azureiac:resourceGroupName: rg-mvp-ukw-storage
  azureiac:storageReplication: LRS
  azureiac:storageAccountTier: Standard

After looking at Pulumi github issues online I found:

https://github.com/pulumi/pulumi/issues/4472

The workaround to start of with is to export those values as env vars as follows:

export PULUMI_CONFIG='
{
	"project:resourceGroupName": "rg-mvp-ukw-storage",
	"project:storageReplication": "LRS",
	"project:storageAccountTier": "Standard "
}'

Once you do this and run dotnet test your tests now run!!!

Microsoft (R) Test Execution Command Line Tool Version 16.7.0
Copyright (c) Microsoft Corporation.  All rights reserved.

Starting test execution, please wait...

A total of 1 test files matched the specified pattern.

Test Run Successful.
Total tests: 1
     Passed: 1

Leave a comment