Tidying Pester API Code

PowerShell's Invoke-RestMethod is a really nice cmdlet to use if you write Rest API test code using the Pester framework. One of the biggest advantages is that if an non-success code is returned from any request you don't have to handle the exception, it gets reported by Pester as an error, stopping the test. The other advantage I would say is that successful calls return a nicely created object rather than a Json document so that tests can use the returned object directly rather than searching in text or having to hydrate a custom object from the Json.

Tests against an (imagined) rest API could look something like this



Describe 'API Get Method' {

	$ApiObject = Invoke-RestMethod -Method Get -Uri $Resource 

	It 'Contains correct number of fields' {
	
		
	}
}

Given that you now have a nice object handed to you by Invoke-RestMethod, it's easy to see that specific fields are present with the correct values but it's difficult to work out if you have the right size of object - that a field hasn't been added or removed by accident.

Luckily, thanks to the introspective nature of PowerShell, you can use Get-Member to work out how many properties have been returned in the Json and converted to properties on the custom object. These properties seem to be a special type of NoteProperty rather than the plain Property type I was expecting.



Get-Member -InputObject $ApiObject -MemberType NoteProperty

Putting that into the body of our test works but it's a bit complex to read and would probably not fair very well if someone was to copy this test as the basis for another.



Describe 'API Get Method' {

	$ApiObject = Invoke-RestMethod -Method Get -Uri $Resource 

	It 'Contains correct number of fields' {
	
		(Get-Member -InputObject $ApiObject -MemberType NoteProperty).Count | Should Be 5
	}
}

To address this, I thought first off to add a custom Pester assertion, as outlined here. That seemed to be too much effort for the tiny bit of tidying I though was warranted by the code so I converted the Get-Member snippet into a cmdlet, Get-FieldCount, that could be used as part of an assertion.



Function Get-FieldCount {
	[CmdletBinding()]
	Param(
		[Parameter(Mandatory=$True, ValueFromPipeline=$True)]
		$InputObject
	)
	
	Process {
		ForEach ($apiObj in $InputObject) {
			$FieldCount = (Get-Member -InputObject $apiObj -MemberType NoteProperty).Count
			Write-Output $FieldCount
		}
	}
}



Describe 'API Get Method' {

	$ApiObject = Invoke-RestMethod -Method Get -Uri $Resource 

	It 'Contains correct number of fields' {
	
		$ApiObject | Get-FieldCount | Should Be 5
	}
}