Mocking New-Object In Pester With PowerShell Classes

When a piece of PowerShell code relies on calling methods in a .NET or COM object using New-Object we want to be able to run these tests without having the underlying .NET or COM object available. We also want to safeguard against any methods in these objects making potentially destructive changes to the systems running the tests.

If the method in the .Net or COM object returns something we can test the value is what we expect. But if the method doesn’t return anything we can’t test if it behaviors as expected. Assert-Mock cannot be used to test if the method was called.

The answer is to Mock the methods in the .Net or COM object being called with a PowerShell class. This allows us to control what they return and also build logic into the class which allows to check if they where called or not, much like Assert-Mock would with normal PowerShell commands\functions.

The above is probably better explained with some example code. Take the function below which adds an OMS (Operations Management Suite) workspace to a local OMS agent.

To test the above code thoroughly we need to be able to track if the methods in the AgentConfigManager.MgmtSvcCfg COM object have been called. To do this we need to Mock the AgentConfigManager.MgmtSvcCfg COM object, this can be achieved by Mocking New-Object with a PowerShell class.

To build the fake AgentConfigManager.MgmtSvcCfg ComObject we first need to see what Methods and Properties are available on the original object via Get-Member.

From this we can build out the PowerShell class that we will use to Mock the object on. We only have to create the methods and properties that our code relies on.

The “fake” class will also include properties that can be set $true\$false depending on whether they have been called or not, this allows us to know if certain methods have been called.  The output of certain methods can also be controlled by setting properties to $true\$false.

The “fake” class below can be used to test our function. It doesn’t include every method\property in the original object, just the ones required to test our function.

We also need to test that our “fake” class doesn’t have methods that are not in original object which we can do again using Pester.

The above Pester test when the methods in the “fake” class are available in the object.

When we add a method to the “fake” class that doesn’t exist in the original Object the test fails.

The below Pester test will test the Add-omsAgentWorkSpace function using the “fake” class.

The successful output of the above Pester test is below.

I would like to hear from people who are doing to it differently or have any improvements on the above.

 

About the author

Ben Taylor

Cloud and PowerShell enthusiast with a penchant for automation and CI.

View all posts

2 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *