A 404 result coming from an Invoke-WebRequest is usually a bad thing. This time, however, the 404 is a result I actually hoped to see. I am creating a custom Azure Devops extension that talks with the API of VMWare VRealize 8. The extension allows users to create a new resources such as a VM within VRA through an Azure Devops Pipeline. The API that I am querying generates a 200 statuscode if the resource with a curtain name exists. If this resource does not exists, a 404 is thrown. I wrote a function that checks 3 things.
- Is the statuscode 200? Throw an error.
- Is the statuscode 404? The test passed and we do not really have to do anything.
- The statuscode is neither 200 or 404? It seems like something else is up, so throw an error with some bonus information.
Function Get-vraDeploymentName { Param ($Uri, $Name, $Headers) $RequestURL = "$Uri/deployment/api/deployments/names/$Name" #Get the statuscode. $Result = try { (Invoke-WebRequest -Uri $RequestURL -Method GET -Headers $Headers) } catch [System.Net.WebException] { $_.Exception.Response } $statusCodeInt = [int]$Result.StatusCode #200 is bad. 404 is good. Everything else is very bad If ($statusCodeInt -eq 200) { Throw "A resource with the name `'$Name`' already exists." } ElseIf ($statusCodeInt -eq 404) { Write-Host "The name `'$Name`' is available for creating the new resource." } Else { throw "Module = Get-vraDeploymentName: $($_.Exception.Message)" } }
How do we test such functionality with Pester? You can mock the Invoke-WebRequest with some JSON output, but this will prevent Pester from testing the try/catch loop. I decided to mock the object ‘System.Net.HttpWebResponse’.
Mock Invoke-WebRequest { $status = [System.Net.WebExceptionStatus]::ConnectionClosed $response = New-MockObject -type 'System.Net.HttpWebResponse' $response | Add-Member -MemberType noteProperty -Name 'StatusCode' -Value 404 -force $exception = New-Object System.Net.WebException "Fout" , $null, $status, $response Throw $exception }
So what is actually happening here?
When running Invoke-WebRequest, PowerShell uses the System.Net assemblies to establish the connection with the API. The result of this action is faked with Mock-Object. Powershell believes that the connection actually failed and it returns the results we need for the test.
Here is the full set of Pester tests I wrote for this particular function.
Describe "Get-vraDeploymentName" { It "Resource exist" { Mock Invoke-WebRequest { @{ StatusCode = 200 } } { Get-vraDeploymentName -Name 'test' -Uri 'http://fakeurl' } | Should -Throw "A resource with the name `'test`' already exists." } It "Resource not exist" { Mock Invoke-WebRequest { $status = [System.Net.WebExceptionStatus]::ConnectionClosed $response = New-MockObject -type 'System.Net.HttpWebResponse' $response | Add-Member -MemberType noteProperty -Name 'StatusCode' -Value 404 -force $exception = New-Object System.Net.WebException "Fout" , $null, $status, $response Throw $exception } Mock Write-Host {} Get-vraDeploymentName -Name 'test' -Uri 'http://fakeurl' Assert-MockCalled Write-Host -Exactly 1 -ParameterFilter { $Object -eq "The name `'test`' is available for creating the new resource." } } It "Failed" { Mock Invoke-WebRequest { } { Get-vraDeploymentName -Name 'test' -Uri 'http://fakeurl' } | Should -Throw "Module = Get-vraDeploymentName: " } }