Search code examples
powershellpester

Issue with script returning $null in Pester test while it shouldn't


So I'm having a bit of an issue in PowerShell I wrote a simple script for a class project about Pester testing It looks like this

param ([Parameter(Mandatory, ValueFromPipeline = $true)]$FN, [Parameter(Mandatory)]$OP, [Parameter()]$SN)

$solution

try {
    if ($OP -eq '+') {

        $solution = ([long]($FN) + [long]($SN))
    
    }

    elseif ($OP -eq '-') {

        $solution = ([long]($FN) - [long]($SN))
    
    }

    elseif ($OP -eq '*') {

        $solution = ([long]($FN) * [long]($SN))
    
    }

    elseif ($OP -eq '/') {

        if ($SecondNumber -eq 0) {
            $solution = "Cannot divide by 0";
        }

        $solution = ([long]($FN) / [long]($SN))
    
    }

    elseif ($OP -eq 'V') {
        $solution = ([math]::Sqrt($FN))
    
    }
    
    else {
        $solution = "Not a valid operator"
    }
    
}
catch {
    Write-Output "An error occured"
}

return $solution

Now this all works fine and when i go into the console and run it with ooutput going into a variable it works fine.

PS C:\PowerShellProject> $test = .\Script.ps1 1 + 1
PS C:\PowerShellProject> $test
2

But then when i run this Pester test

Describe "Test for Script.ps1" {
    Context "Testing calculations" {
        It "+ test" {
            $plus = .\Test.ps1 -FN 2 -OP + -SN 2
            $plus | Should -Be 4
        }
    }
}

It returns the following

PS C:\PowerShellProject> Invoke-Pester .\Test.ps1

Starting discovery in 1 files.
Discovery found 1 tests in 15ms.
Running tests.

[-] Test for Script.ps1.Testing calculations.+ test 18ms (16ms|2ms)
 Expected 4, but got $null.
 at $plus | Should -Be 4, C:\PowerShellProject\Test.ps1:6
 at <ScriptBlock>, C:\PowerShellProject\Test.ps1:6
[-] Context Test for Script.ps1.Testing calculations failed
 InvalidOperationException: Collection was modified; enumeration operation may not execute.

Tests completed in 156ms
Tests Passed: 0, Failed: 1, Skipped: 0 NotRun: 1
BeforeAll \ AfterAll failed: 1
  - Test for Script.ps1.Testing calculations

I'm still pretty new to Powershell so I must probably be making a silly mistake here.

Maybe someone could redirect me to another question that had a similar problem or give me a solution to my problem. This would be really helpful since I have been breaking my head over this for a couple of hours and it's really starting to annoy me.


Solution

  • The problem is this line at the start of your function:

    $solution
    

    This does not declare the variable, as you propably expect, but due to PowerShells implicit output behaviour, it actually outputs the variable. The output is $null as the variable has not been defined yet.

    To actually define the variable you have to assign a value:

    $solution = 0
    

    Later, when you do return $solution, you are actually adding another value to the output stream, which when captured to a variable, will be the array @($null, 2).

    Proof:

    $plus = .\Test.ps1 -FN 2 -OP + -SN 2            
    Write-Host $plus.GetType().Name
    

    This prints Object[], although we would expect int.

    In PowerShell you usually don't use the return statement, except when you want to early exit from a function. return $solution is actually just a shortcut for:

    $solution  # implicit output
    return     # exit from function
    

    There is another issue in your Pester test script, where you are calling the wrong script. It should be:

    $plus = .\Script.ps1 -FN 2 -OP + -SN 2