Search code examples
powershellpester

How to Pester-test a method in a class module (.psm1)?


I have written multiple classes. All of them are being used interchangeably. The main script (Main.ps1) imports some of them and runs the program.

I'd like to create Pester tests for each one of these class modules (.psm1) that I've created, including their methods.

class MyClass
{
    [string]GetID()
    {
        [string]$id = New-Guid
        return $id
    }
}

How do I import MyClass, and how do I mock New-Guid in Pester?


Solution

  • Create a Pester script MyClass.GetID.Tests.ps1 containing something like this:

    using module ".\MyClass.psm1"
    
    Describe "GetID() method flows" {
        InModuleScope "MyClass" {
            $mockObject = [MyClass]::new()
            $mockGuid   = "guid"
    
            Mock New-Guid { 
                return $mockGuid 
            }
    
            Context "Happy flow" {
                It "Should return the guid" {
                    $result = $mockObject.GetID()
                    $result | Should -Be $mockGuid
    
                    Assert-MockCalled New-Guid -Scope It -Exactly 1
                }
            }
        }
    }
    

    You can also dot-source the class module:

    . ".\MyClass.psm1"
    
    Describe "GetID() method flows" {
        BeforeAll {
            $mockObject = [MyClass]::new()
            $mockGuid   = "guid"
    
            Mock New-Guid { 
                return $mockGuid 
            }
        }
    
        Context "Happy flow" {
            It "Should return the guid" {
                $result = $mockObject.GetID()
                $result | Should -Be $mockGuid
    
                Assert-MockCalled New-Guid -Scope It -Exactly 1
            }
        }
    }
    

    Of course it is also possible to test all methods from the same test script. Please note that PowerShell has no way to unload a class. This means changes to the class are usually not available until you restart the PowerShell session.