Search code examples
unit-testingpowershellpester

Pester reset test data


This is about scope of test data in pester. I am testing a function Add-HashTableIfNotPresent which checks for the existence of a key in a hashtable, if it doesn't exist it adds it otherwise it returns the value linked to that key.

I have 2 It blocks for my pester test that check the 2 scenarios - key exists and key doesn't exist. I was expecting $ht to be recreated for each It block but it's not so if I swap the order of my 2 Its then Returns existing entry when passed existing key fails because $ht.count is still 3.

Is there a way to get $ht reset for each test or do I need to define it inside the It block?

Function under test:

function Add-HashTableIfNotPresent {
    [CmdletBinding()]
    param(
        [hashtable] $sourceTable,
        [string] $keyToCheck
    )

    $subTable = $sourceTable.$keyToCheck
    if(-not $subTable){
        $subTable = @{}
        $sourceTable.$keyToCheck = $subTable
    }
}

Test code:

Describe 'Add-HashTableIfNotPresent' {
    $ht = @{
        subTable1 = @{
            st1 = "abc"
        }
        subTable2 = @{
            st2 = "def"
        }
    }

    It "Returns existing entry when passed existing key" {
        Add-HashTableIfNotPresent -sourceTable $ht -keyToCheck subTable2
        $ht.Count | Should BeExactly 2
        $value = $ht.subTable2
        $value.count | Should BeExactly 1
        $value.st2 | Should -Be "def"
    }

    It "Adds entry that doesn't exist" {
        Add-HashTableIfNotPresent -sourceTable $ht -keyToCheck subTable3
        $ht.Count | Should BeExactly 3
        $addedValue = $ht.subTable3
        $addedValue | Should -Be $true
        $addedValue.count | Should BeExactly 0
    }
}

Solution

  • Context and Describe blocks have scopes that mean variables defined in them are restricted to that specific block and don't exist outside it, but your variables still aren't then automatically reset for each It test.

    I would suggest using a Function to set your hashtable before each test:

    Function Set-TestHashTable {
        @{
            subTable1 = @{
                st1 = "abc"
            }
            subTable2 = @{
                st2 = "def"
            }
        }
    }
    
    Describe 'Add-HashTableIfNotPresent' {
    
        $ht = Set-TestHashTable
    
        It "Returns existing entry when passed existing key" {
            Add-HashTableIfNotPresent -sourceTable $ht -keyToCheck subTable2
            $ht.Count | Should BeExactly 2
            $value = $ht.subTable2
            $value.count | Should BeExactly 1
            $value.st2 | Should -Be "def"
        }
    
        $ht = Set-TestHashTable
    
        It "Adds entry that doesn't exist" {
            Add-HashTableIfNotPresent -sourceTable $ht -keyToCheck subTable3
            $ht.Count | Should BeExactly 3
            $addedValue = $ht.subTable3
            $addedValue | Should -Be $true
            $addedValue.count | Should BeExactly 0
        }
    }