Search code examples
powershellpester

How to properly Pester test Import-Clixml


So first of all I need to state that I am quite new to Pester and might not be writing my tests correctly or don't properly understand all its functionality.

So background is that I want to automate my PowerShell module with Pester and have written some tests so far.

Part of my module is saving configuration stuff in a clixml file. I would like to write a set of tests to make sure saving and grabbing the configuration works as expected.

Basically I have one function to save the configuration file and one to retrieve it. My Pester test looks as the following:

BeforeAll{
        if(Test-path existingconfigfile.xml){

            Rename-Item -Path "existingconfigfile" -NewName "backup.xml"
        }

        Save-configfunction -param1 'Value1' -param2 'Value2'
        #saves as test.xml
    }

    Afterall{
        if(Test-path backup.xml){

            # Remove mocked test file
            Remove-Item -Path "test.xml" -Force

            # Place original back
            Rename-Item -Path "backup.xml" -NewName "existingconfigfile.xml"
        }
    }

    it "importconfig should return expected values for mocked object" {

        {
            $result = Get-config
            $result
            $result.Containsvalue('Value1') | Should be $true

        }
    }

Now I've tried a couple of variations of the it block:

it "importconfig should return expected values for mocked object" {

        {
            $result = Get-config
            $result.param1 | Should be "Value1"
        }
    }

    it "importconfig should return expected values for mocked object" {
        $result = Get-Config

        $result | Should match 'Value1'
        $result | Should match 'Value2'
    }

    it "importconfig should return expected values for mocked object" {

        $result = Get-Config

        $result.Param1 | Should match 'Value1'
        $result.Param2 | Should match 'Value2'
    }

Pester always returns a passed test even if I change the match values to incorrect ones. Pester does this in all scenarios. So for some reason Pester does not qualify the values correctly and always returns a positive result.

So I'd like to know what I am doing wrong. Obviously Pester should pass the test if the values actually match, but it should fail when they do not match.


Solution

  • I think rather than using BeforeAll and AfterAll to create Mock type behaviour for modifying the config, I would use actual Mock statements. Here's what I mean (I've created simple representations of what I assume your functions do as you haven't shared them):

    function Set-Config {
        Param(
            $Config
        )
        $Config | Export-Clixml C:\Temp\production_config.xml
    }
    
    function Get-Config {
        Import-Clixml C:\Temp\production_config.xml
    }
    
    Describe 'Config function tests' {
    
        Mock Set-Config {
            $Config | Export-Clixml TestDrive:\test_config.xml
        }
    
        Mock Get-Config {
            Import-Clixml TestDrive:\test_config.xml
        }
    
        $Config = @{
            Setting1 = 'Blah'
            Setting2 = 'Hello'
        }
    
        It 'Sets config successfully' {
            { Set-Config -Config $Config } | Should -Not -Throw
        }
    
        $RetrievedConfig = Get-Config
    
        It 'Gets config successfully' {
            $RetrievedConfig.Setting1 | Should -Be 'Blah'
            $RetrievedConfig.Setting2 | Should -Be 'Hello'
        }
    }
    

    This creates Mocks of the Get-Config and Set-Config functions that redirect the write/read of the config to TestDrive:\ which is a special temporary disk area that Pester provides and cleans up automatically afterwards.

    Note that this only makes sense when testing a parent function that makes use of these functions. If you were writing tests of the Get-Config and Set-Config functions themselves then you'd instead want to be mocking the Export-CliXml and Import-CliXml commands.