1

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?

DAG
  • 2,460
  • 5
  • 33
  • 61

2 Answers2

3
$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.

zett42
  • 25,437
  • 3
  • 35
  • 72
  • Sorry, but that is not even compiling :( I'm wondering how to use that within `Assert-MockCalled` – DAG Mar 14 '21 at 17:20
  • @DAG You are right, I've fixed the code and show how to use it as part of your original code. – zett42 Mar 14 '21 at 18:00
  • Thanks, it's compiling now, but it always returns `$true` .For example if you change `terms.txt` to `terms2.txt` the test still is green. – DAG Mar 14 '21 at 18:28
  • @DAG It works for me. When I change it like this, the test fails as expected. PS 7.1.3, Pester 5.1.0. – zett42 Mar 14 '21 at 18:36
  • It works indeed. I had a small typo :) Thanks – DAG Mar 14 '21 at 18:59
0

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.

Max Cascone
  • 648
  • 9
  • 25