Search code examples
unit-testingpowershellpester

Assert-MockCalled vs Assert-VerifiableMocks in Pester


What makes Assert-VerifiableMocks different from Assert-MockCalled in Pester? I've been reading

but still wonder: are the following sections of code equivalent and interchangeable?

Using Assert-MockCalled:

Mock Invoke-MongoCommmand {}
Set-TargetResource -UserName $test_username -Ensure "Absent"
Assert-MockCalled Invoke-MongoCommand -ParameterFilter {
    $Expression -eq "db.dropUser('$test_username')"
}

Using Assert-VerifiableMocks:

Mock Invoke-MongoCommand {} -Verifiable -ParameterFilter {
    $Expression -eq "db.dropUser('$test_username')"
}
Set-TargetResource -UserName $test_username -Ensure "Absent"
Assert-VerifiableMocks

Solution

  • The functionality of Assert-VerifiableMocks isn't a subset of Assert-MockCalled it's a disjoint set. With Assert-VerifiableMocks you can verify many mocks are called at the same time, but as already mentioned you cannot verify any mocks are not called. I have an example below to more fully explain these two differences testing an example 'Get-ValueSum'.

    If you notice with Assert-verifiableMocks you can verify that the test has called all the expected mocks in a single assert.

    Assert-Verifiable Sample

    describe 'Assert-MockCalled vs Assert-VerifiableMocks in Pester' {
        function Get-Value1{ 1}
        function Get-Value2{ 2}
        function Get-Value3{ 3}
        
        # Should never be called by Get-ValueSum
        function Get-Value4{ 4}
    
        # Sums Value 1, 2 & 3, but 4 only if $include4 is specified
        function Get-ValueSum
        {
            param([switch] $inclued4 )
            if($inclued4)
            {
                return (Get-Value1) + (Get-Value2) + (Get-Value3) + (Get-Value4)
            }
            else
            {
                return (Get-Value1) + (Get-Value2) + (Get-Value3)
            }
        }
    
        context 'assert verifiable' {
            # Mark the first 3 mocks as verifiable 
            # because they should not be called 
            mock -CommandName Get-Value1 -MockWith { 2} -Verifiable
            mock -CommandName Get-Value2 -MockWith { 3} -Verifiable
            mock -CommandName Get-Value3 -MockWith { 4} -Verifiable
            # Add this so we can verify it is not called
            mock -CommandName Get-Value4 -MockWith { 99} 
            
            $result = Get-ValueSum
    
            it 'Should call the 3 expected value calls' {
                Assert-VerifiableMock
            }
    
            it 'should not call get-value 4' {
                Assert-MockCalled -CommandName Get-Value4 -Times 0
            }
    
            it 'should have gotten a sum of 9' {
                $result | should be 9
            }
            # add test for #$include4
        }
    }
    

    Assert-MockCalled Sample

    describe 'Assert-MockCalled vs Assert-VerifiableMocks in Pester' {
        function Get-Value1{ 1}
        function Get-Value2{ 2}
        function Get-Value3{ 3}
        
        # Should never be called by Get-ValueSum
        function Get-Value4{ 4}
    
        # Sums Value 1, 2 & 3, but 4 only if $include4 is specified
        function Get-ValueSum
        {
            param([switch] $inclued4 )
            if($inclued4)
            {
                return (Get-Value1) + (Get-Value2) + (Get-Value3) + (Get-Value4)
            }
            else
            {
                return (Get-Value1) + (Get-Value2) + (Get-Value3)
            }
        }
    
        context 'assert mock called method' {
            # Add all mocks so we can verify 
            # if they were called or not individually
            mock -CommandName Get-Value1 -MockWith { 3} 
            mock -CommandName Get-Value2 -MockWith { 4} 
            mock -CommandName Get-Value3 -MockWith { 5} 
            mock -CommandName Get-Value4 -MockWith { 99} 
    
            $result = Get-ValueSum
    
            it 'Should call the 3 expected value calls' {
                Assert-MockCalled -CommandName Get-Value1 -Times 1
                Assert-MockCalled -CommandName Get-Value2 -Times 1
                Assert-MockCalled -CommandName Get-Value3 -Times 1
            }
    
            it 'should not call get-value 4' {
                Assert-MockCalled -CommandName Get-Value4 -Times 0
            }
    
            it 'should have gotten a sum of 12' {
                $result | should be 12
            }
            # add test for #$include4
        }
    }