DAG
DAG

Reputation: 2630

Assert array in ParameterFilter for Pester Assert-MockCalled

We are trying to assert a call with specific parameter which is an array and it's returning false in Assert-MockCalled, for all other parameters which are not array it's working (string types).

Here is my example:

function NewZip ($Name) {
    $compress = @{
        Path             = "$PSScriptRoot/terms.txt", "$PSScriptRoot/fav.ico"
        CompressionLevel = "Fastest"
        DestinationPath  = "$PSScriptRoot/$Name.zip"
    }

    Compress-Archive @compress -Update
}

It "Creates a zip file" {
    # Arrange
    $name = "test"
    $assertParams = @{
        CommandName     = 'Compress-Archive'
        Times           = 1
        ParameterFilter = { 
            $Path -in "$PSScriptRoot/terms.txt", "$PSScriptRoot/fav.ico" -and
            $DestinationPath -eq "$PSScriptRoot/$name.zip" -and
            $CompressionLevel -eq  "Fastest" -and
            $Update -eq $true
        }
    }

    Mock Compress-Archive {}

    # Act
    NewPackage -Name $name

    # Assert
    Assert-MockCalled @assertParams
}

How can I use array comparison within Assert-MockCalled?

Upvotes: 1

Views: 721

Answers (2)

Max Cascone
Max Cascone

Reputation: 833

This is a tricky one! I spent most of a day on this.

This was failing:

Mock Invoke-MyFunc { } -Verifiable -ParameterFilter { $realArray -eq $testArray }

because as the answers above detail, you can't compare arrays this way.

I ended up with:

Mock Invoke-MyFunc { } -Verifiable -ParameterFilter { (Compare-Object $realArray $testArray).length -eq 0 }

Because if the length is zero, the arrays are equal, and we need to return a boolean in the ParameterFilter.

Upvotes: 0

zett42
zett42

Reputation: 27776

$Path -in "$PSScriptRoot/terms.txt", "$PSScriptRoot/fav.ico"

can't work because:

When the test object is a set, these operators use reference equality to check whether one of the set's elements is the same instance of the test object.

You can use Compare-Object instead to do a value comparison:

ParameterFilter = { 
    -not (Compare-Object $Path "$PSScriptRoot/terms.txt", "$PSScriptRoot/fav.ico") -and
    $DestinationPath -eq "$PSScriptRoot/$name.zip" -and
    $CompressionLevel -eq  "Fastest" -and
    $Update -eq $true
}

The negation is required because Compare-Object outputs the differences. It outputs nothing if the arrays are equal. When captured, "nothing" turns into $null which converts to $false in a boolean context.

The parentheses (aka group operator) are required in order to use the output of Compare-Object in an expression.

Upvotes: 3

Related Questions