powershellpesterpester-5

Test Invocations of `Set-NetFirewallProfile` having the `-Profile` argument using Pester mocking


I am working on some unit tests for a powershell module and I am at a loss for how to test if the Set-NetfirewallProfile was called with the correct parameters. It seems that I am not correctly filtering for the -Profile argument.

I've scoured the web for any documentation on the parameter, I've used the debug option in vscode to see how it was called:

...
Mock: Running mock filter {
$Enabled -eq $false -and $PesterBoundParameters.Profile -eq "Domain,Public,Private"                                                                                               
         } with context: Profile = Domain Public Private, Name = Domain Public Private, Enabled = False.
Mock: Mock filter returned value 'False', which is falsy. Filter did not pass.
...

I've tried to modify the filters I am using based on this info, but the test still fails.

Here is a simplified version of the test that is failing (but should pass):

Describe "Test-Example" {
    BeforeAll {
        # Example unit under test:
        function Test-Example {
            Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled False
        }
        Mock Set-NetFirewallProfile
    }

    It "should disable the firewall" {
        Test-Example
        Should -Invoke -CommandName Set-NetFirewallProfile -Times 1 -Exactly -ParameterFilter {
            $Enabled -eq $false -and $PesterBoundParameters.Profile -eq "Domain,Public,Private"
        } -Scope It
    }
}

I tried to use this filter for the Profile instead, which failed: $PesterBoundParameters.Profile -eq "Domain Public Private"

If I remove $PesterBoundParameters.Profile -eq "Domain,Public,Private" from the Parameter filters, the test then passes.


Solution

  • The problem here is that $Profile holds and array of @("Domain", "Public", "Private") and not string, so you have to compare against an array.

    I omitted for brevity the rest of the code leaving only ParameterFilter:

    -ParameterFilter { @(Compare-Object $Profile @('Domain', 'Public', 'Private') -SyncWindow 0).Length -eq 0 -and $Enabled -eq $false }
    

    Comparing two arrays for equality in powershell is a feat :) here is the comperhensive answer that explains how Compare-Object can be used for arrays equality check.