Steven Betz
Steven Betz

Reputation: 1

Pester 5.X : Mocking of PowerCLI Commands doesn't work

For our automatic vm deployment workflow in vSphere I wrote a small powershell function to return a destination esx host based on the given cluster. Everything works fine for me.

function Find-VcDestinationHost {
<#
    .SYNOPSIS
        Finds an ESX Host for VM installations.
    .DESCRIPTION
        Idendifies a suitable ESX Host for Windows or Linux VM installations using the given cluster name
    .EXAMPLE
        Find-VcDestinationHost -Cluster Cluster1
    .PARAMETER Cluster
        Destination Cluster from which the destination esx host should be chosen.
    #>
    param (
        [Parameter(Mandatory = $true, Position = 1)]
        [string]$Cluster
    )

    $TranscriptDir = Get-PSFConfigValue -FullName 'Base.TranscriptDir' -Fallback 'c:\scripts\transcripts\'
    if (-not (Test-Path -Path $TranscriptDir))
    {
        New-Item -ItemType Directory -Path $TranscriptDir
    }
    try {
        Start-Transcript (Join-Path $TranscriptDir ($MyInvocation.MyCommand.Name + '.txt')) -Append -ErrorAction Stop | Out-Null
    } catch {
        Start-Transcript (Join-Path $TranscriptDir ($MyInvocation.MyCommand.Name + (Get-Random) + '.txt')) -Append -ErrorAction SilentlyContinue | Out-Null
    }

    $viservers = Get-PSFConfigValue -FullName 'VC.vCenterList'
    connect-viserver $viservers


    #Region Find Destination Host
        $ClusterObj = Get-Cluster $Cluster
        if (-not $ClusterObj) {
            throw "Das Cluster wurde in keinem vCenter gefunden!"
        }
        $VMHostObj = Get-VMHost -Location $ClusterObj | Where-Object { $_.ConnectionState -eq "Connected" } | Get-Random
        if (-not $VMHostObj) {
            throw "Es wurde kein passender ESX Host gefunden!"
        }
        Write-Output "Gewählter Ziel-Host:"
        Write-Output ($VMHostObj | Select-Object -ExpandProperty Name | Out-String)
    #endregion

    Disconnect-VIServer $viservers -Force -Confirm:$false

    Write-Output "Variablen:"
    Write-Output "##DestinationHost##$($VMHostObj.Name)##"

    Stop-transcript -ErrorAction SilentlyContinue | Out-Null
}

But while writing some pester unit tests for the function I got stuck.. None of the used PowerCli cmdlets can be mocked. Pester tries to call the original powercli function every time. (The tests should work without a connection to the vsphere environment) How can I mock these PowerCli cmdlets? Here are my written tests:

Describe "Find-VcDestinationHost Tests" {
    Context "Setting up a Mock from a Function" {
        BeforeEach {
            . source\Public\Find-VcDestinationHost.ps1


            Mock -CommandName Get-PSFConfigValue -MockWith {
                param ($FullName, $Fallback)
                if ($FullName -eq 'Base.TranscriptDir') {
                    return 'c:\\scripts\\transcripts\\'
                } elseif ($FullName -eq 'VC.vCenterList') {
                    return 'vcenter1'
                }
            }

            Mock -CommandName Test-Path -MockWith { return $false }
            Mock -CommandName New-Item -MockWith { return $null }
            Mock -CommandName Start-Transcript -MockWith { return $null }
            Mock -CommandName Connect-VIServer -MockWith { return $null }
            Mock -CommandName Get-Cluster -MockWith { return "Cluster1" }
            Mock -CommandName Get-VMHost -MockWith {
                param ($Location)
                return [PSCustomObject]@{ Name = "MockVMHost" }
            }
            Mock -CommandName Disconnect-VIServer -MockWith { return $null }
            Mock -CommandName Stop-Transcript -MockWith { return $null }
        }

        It "Should find a destination host" {
            Find-VcDestinationHost -Cluster "Cluster1" | Should -Contain "MockVMHost"
        }
    }
}

I already tried to mock the commands with parameter filters, returning PSCustomObjects with the required parameters or declaring own functions like "Get-Cluster" with a simple return object.

Once pester succesfully mocked "Get-Cluster" but then the Get-VMHost couldn't work with my returned output of the mock.

Upvotes: 0

Views: 21

Answers (0)

Related Questions