Tests/Unit/MSFT_SmbShare.Tests.ps1

#region HEADER
$script:dscModuleName = 'ComputerManagementDsc'
$script:dscResourceName = 'MSFT_SmbShare'

Import-Module -Name (Join-Path -Path (Join-Path -Path (Split-Path $PSScriptRoot -Parent) -ChildPath 'TestHelpers') -ChildPath 'CommonTestHelper.psm1') -Global

# Unit Test Template Version: 1.2.4
$script:moduleRoot = Split-Path -Parent (Split-Path -Parent $PSScriptRoot)
if ( (-not (Test-Path -Path (Join-Path -Path $script:moduleRoot -ChildPath 'DSCResource.Tests'))) -or `
    (-not (Test-Path -Path (Join-Path -Path $script:moduleRoot -ChildPath 'DSCResource.Tests\TestHelper.psm1'))) )
{
    & git @('clone', 'https://github.com/PowerShell/DscResource.Tests.git', (Join-Path -Path $script:moduleRoot -ChildPath 'DscResource.Tests'))
}

Import-Module -Name (Join-Path -Path $script:moduleRoot -ChildPath (Join-Path -Path 'DSCResource.Tests' -ChildPath 'TestHelper.psm1')) -Force

$TestEnvironment = Initialize-TestEnvironment `
    -DSCModuleName $script:dscModuleName `
    -DSCResourceName $script:dscResourceName `
    -ResourceType 'Mof' `
    -TestType Unit
#endregion HEADER

function Invoke-TestSetup
{
}

function Invoke-TestCleanup
{
    Restore-TestEnvironment -TestEnvironment $TestEnvironment
}

try
{
    Invoke-TestSetup

    InModuleScope $script:DSCResourceName {
        $mockShareName = 'TestShare'
        $mockChangePermissionUserName = @('User1')
        $mockReadPermissionUserName = @('User2')
        $mockFullPermissionUserName = @('User3', 'User4')
        $mockNoPermissionUserName = @('DeniedUser1')

        $mockSmbShare = (
            New-Object -TypeName Object |
            Add-Member -MemberType NoteProperty -Name 'Name' -Value $mockShareName -PassThru |
            Add-Member -MemberType NoteProperty -Name 'Path' -Value 'c:\temp' -PassThru |
            Add-Member -MemberType NoteProperty -Name 'Description' 'Dummy share for unit testing' -PassThru |
            Add-Member -MemberType NoteProperty -Name 'ConcurrentUserLimit' -Value 10 -PassThru |
            Add-Member -MemberType NoteProperty -Name 'EncryptData' -Value $false -PassThru |
            # 0 AccessBased | 1 Unrestricted
            Add-Member -MemberType NoteProperty -Name 'FolderEnumerationMode' -Value 'AccessBased' -PassThru |
            # 0 Pending | 1 Online | 2 Offline
            Add-Member -MemberType NoteProperty -Name 'ShareState' -Value 'Online' -PassThru |
            Add-Member -MemberType NoteProperty -Name 'ShareType' -Value 'FileSystemDirectory' -PassThru |
            Add-Member -MemberType NoteProperty -Name 'ShadowCopy' -Value $false -PassThru |
            Add-Member -MemberType NoteProperty -Name 'CachingMode' -Value 'Manual' -PassThru |
            Add-Member -MemberType NoteProperty -Name 'ContinuouslyAvailable' -Value $true -PassThru |
            Add-Member -MemberType NoteProperty -Name 'Special' -Value $false -PassThru -Force
        )

        $mockSmbShareAccess = @(
            (
                New-Object -TypeName Object |
                Add-Member -MemberType NoteProperty -Name 'Name' -Value $mockShareName -PassThru |
                Add-Member -MemberType NoteProperty -Name 'ScopName' -Value '*' -PassThru |
                Add-Member -MemberType NoteProperty -Name 'AccountName' -Value $mockFullPermissionUserName[0] -PassThru |
                Add-Member -MemberType NoteProperty -Name 'AccessControlType' -Value 'Allow' -PassThru |
                Add-Member -MemberType NoteProperty -Name 'AccessRight' -Value 'Full' -PassThru -Force
            ),
            (
                New-Object -TypeName Object |
                Add-Member -MemberType NoteProperty -Name 'Name' -Value $mockShareName -PassThru |
                Add-Member -MemberType NoteProperty -Name 'ScopName' -Value '*' -PassThru |
                Add-Member -MemberType NoteProperty -Name 'AccountName' -Value $mockFullPermissionUserName[1] -PassThru |
                Add-Member -MemberType NoteProperty -Name 'AccessControlType' -Value 'Allow' -PassThru |
                Add-Member -MemberType NoteProperty -Name 'AccessRight' -Value 'Full' -PassThru -Force
            ),
            (
                New-Object -TypeName Object |
                Add-Member -MemberType NoteProperty -Name 'Name' -Value $mockShareName -PassThru |
                Add-Member -MemberType NoteProperty -Name 'ScopName' -Value '*' -PassThru |
                Add-Member -MemberType NoteProperty -Name 'AccountName' -Value $mockChangePermissionUserName[0] -PassThru |
                Add-Member -MemberType NoteProperty -Name 'AccessControlType' -Value 'Allow' -PassThru |
                Add-Member -MemberType NoteProperty -Name 'AccessRight' -Value 'Change' -PassThru -Force
            ),
            (
                New-Object -TypeName Object |
                Add-Member -MemberType NoteProperty -Name 'Name' -Value $mockShareName -PassThru |
                Add-Member -MemberType NoteProperty -Name 'ScopName' -Value '*' -PassThru |
                Add-Member -MemberType NoteProperty -Name 'AccountName' -Value $mockReadPermissionUserName[0] -PassThru |
                Add-Member -MemberType NoteProperty -Name 'AccessControlType' -Value 'Allow' -PassThru |
                Add-Member -MemberType NoteProperty -Name 'AccessRight' -Value 'Read' -PassThru -Force
            ),
            (
                New-Object -TypeName Object |
                Add-Member -MemberType NoteProperty -Name 'Name' -Value $mockShareName -PassThru |
                Add-Member -MemberType NoteProperty -Name 'ScopName' -Value '*' -PassThru |
                Add-Member -MemberType NoteProperty -Name 'AccountName' -Value $mockNoPermissionUserName[0] -PassThru |
                Add-Member -MemberType NoteProperty -Name 'AccessControlType' -Value 'Deny' -PassThru |
                Add-Member -MemberType NoteProperty -Name 'AccessRight' -Value 'Full' -PassThru -Force
            )
        )

        Describe 'MSFT_SmbShare\Get-TargetResource' -Tag 'Get' {
            Context 'When the system is in the desired state' {
                BeforeAll {
                    Mock -CommandName Get-SmbShare -MockWith {
                        return $mockSmbShare
                    }

                    Mock -CommandName Get-SmbShareAccess -MockWith {
                        return $mockSmbShareAccess
                    }

                    $testParameters = @{
                        Name    = $mockSmbShare.Name
                        Path    = $mockSmbShare.Path
                        Verbose = $true
                    }
                }

                It 'Should return the correct access memberships' {
                    $getTargetResourceResult = Get-TargetResource @testParameters

                    $getTargetResourceResult.ChangeAccess | Should -HaveCount 1
                    $getTargetResourceResult.ChangeAccess[0] | Should -BeIn $mockChangePermissionUserName

                    $getTargetResourceResult.ReadAccess | Should -HaveCount 1
                    $getTargetResourceResult.ReadAccess[0] | Should -BeIn $mockReadPermissionUserName

                    $getTargetResourceResult.FullAccess | Should -HaveCount 2
                    $getTargetResourceResult.FullAccess[0] | Should -BeIn $mockFullPermissionUserName
                    $getTargetResourceResult.FullAccess[1] | Should -BeIn $mockFullPermissionUserName

                    $getTargetResourceResult.NoAccess | Should -HaveCount 1
                    $getTargetResourceResult.NoAccess[0] | Should -BeIn $mockNoPermissionUserName

                    Assert-MockCalled Get-SmbShare -Exactly -Times 1 -Scope It
                    Assert-MockCalled Get-SmbShareAccess -Exactly -Times 1 -Scope It
                }
            }

            Context 'When the system is not in the desired state' {
                BeforeAll {
                    Mock -CommandName Get-SmbShare

                    $testParameters = @{
                        Name    = $mockSmbShare.Name
                        Path    = $mockSmbShare.Path
                        Verbose = $true
                    }
                }

                It 'Should return the correct values' {
                    $getTargetResourceResult = Get-TargetResource @testParameters

                    $getTargetResourceResult.Ensure | Should -Be 'Absent'
                    $getTargetResourceResult.Name | Should -Be $testParameters.Name
                    $getTargetResourceResult.Path | Should -BeNullOrEmpty
                    $getTargetResourceResult.Description | Should -BeNullOrEmpty
                    $getTargetResourceResult.ConcurrentUserLimit | Should -Be 0
                    $getTargetResourceResult.EncryptData | Should -BeFalse
                    $getTargetResourceResult.FolderEnumerationMode | Should -BeNullOrEmpty
                    $getTargetResourceResult.CachingMode | Should -BeNullOrEmpty
                    $getTargetResourceResult.ContinuouslyAvailable | Should -BeFalse
                    $getTargetResourceResult.ShareState | Should -BeNullOrEmpty
                    $getTargetResourceResult.ShareType | Should -BeNullOrEmpty
                    $getTargetResourceResult.ShadowCopy | Should -BeFalse
                    $getTargetResourceResult.Special | Should -BeFalse
                    $getTargetResourceResult.ChangeAccess | Should -HaveCount 0
                    $getTargetResourceResult.ReadAccess | Should -HaveCount 0
                    $getTargetResourceResult.FullAccess | Should -HaveCount 0
                    $getTargetResourceResult.NoAccess | Should -HaveCount 0

                    Assert-MockCalled Get-SmbShare -Exactly -Times 1 -Scope It
                }
            }
        }

        Describe 'MSFT_SmbShare\Set-TargetResource' -Tag 'Set' {
            Context 'When the system is not in the desired state' {
                BeforeAll {
                    Mock -CommandName New-SmbShare
                    Mock -CommandName Set-SmbShare
                    Mock -CommandName Remove-SmbShareAccessPermission
                    Mock -CommandName Add-SmbShareAccessPermission
                    Mock -CommandName Remove-SmbShare
                }

                Context 'When the configuration should be present' {
                    BeforeAll {
                        Mock -CommandName Get-TargetResource -MockWith {
                            return @{
                                Name                  = $mockShareName
                                Path                  = $null
                                Description           = $null
                                ConcurrentUserLimit   = [System.UInt32] 0
                                EncryptData           = $false
                                FolderEnumerationMode = $null
                                CachingMode           = $null
                                ContinuouslyAvailable = $false
                                ShareState            = $null
                                ShareType             = $null
                                ShadowCopy            = $false
                                Special               = $false
                                FullAccess            = [System.String[]] @()
                                ChangeAccess          = [System.String[]] @()
                                ReadAccess            = [System.String[]] @()
                                NoAccess              = [System.String[]] @()
                                Ensure                = 'Absent'
                            }
                        }
                    }

                    Context 'When no access permission is given' {
                        It 'Should throw the correct error' {
                            $setTargetResourceParameters = @{
                                Name                  = $mockShareName
                                Path                  = 'TestDrive:\Temp'
                                Description           = 'Some description'
                                ConcurrentUserLimit   = 2
                                EncryptData           = $false
                                FolderEnumerationMode = 'AccessBased'
                                CachingMode           = 'Manual'
                                ContinuouslyAvailable = $true
                                ChangeAccess          = @()
                                ReadAccess            = @()
                                FullAccess            = @()
                                NoAccess              = @()
                                Verbose               = $true
                            }

                            { Set-TargetResource @setTargetResourceParameters } | Should -Throw $script:localizedData.WrongAccessParameters
                        }
                    }

                    Context 'When access permissions are given' {
                        It 'Should call the correct mocks' {
                            $setTargetResourceParameters = @{
                                Name                  = $mockShareName
                                Path                  = 'TestDrive:\Temp'
                                Description           = 'Some description'
                                ConcurrentUserLimit   = 2
                                EncryptData           = $false
                                FolderEnumerationMode = 'AccessBased'
                                CachingMode           = 'Manual'
                                ContinuouslyAvailable = $true
                                ChangeAccess          = $mockChangePermissionUserName
                                ReadAccess            = $mockReadPermissionUserName
                                FullAccess            = $mockFullPermissionUserName
                                NoAccess              = $mockNoPermissionUserName
                                Verbose               = $true
                            }

                            { Set-TargetResource @setTargetResourceParameters } | Should -Not -Throw

                            Assert-MockCalled New-SmbShare -Exactly -Times 1 -Scope It
                            Assert-MockCalled Set-SmbShare -Exactly -Times 0 -Scope It
                            Assert-MockCalled Remove-SmbShare -Exactly -Times 0 -Scope It
                            Assert-MockCalled Remove-SmbShareAccessPermission -Exactly -Times 0 -Scope It
                        }
                    }
                }

                Context 'When the configuration should be absent' {
                    BeforeAll {
                        Mock -CommandName Get-TargetResource -MockWith {
                            return @{
                                Name   = $mockShareName
                                Ensure = 'Present'
                            }
                        }
                    }

                    It 'Should call the correct mocks' {
                        $setTargetResourceParameters = @{
                            Name    = $mockShareName
                            Path    = 'AnyValue'
                            Ensure  = 'Absent'
                            Verbose = $true
                        }

                        { Set-TargetResource @setTargetResourceParameters } | Should -Not -Throw

                        Assert-MockCalled New-SmbShare -Exactly -Times 0 -Scope It
                        Assert-MockCalled Set-SmbShare -Exactly -Times 0 -Scope It
                        Assert-MockCalled Remove-SmbShare -Exactly -Times 1 -Scope It
                    }
                }

                Context 'When the configuration has a property that is not in desired state' {
                    BeforeAll {
                        Mock -CommandName Get-TargetResource -MockWith {
                            return @{
                                Name                  = $mockSmbShare.Name
                                Path                  = $mockSmbShare.Path
                                Description           = $mockSmbShare.Description
                                ConcurrentUserLimit   = [System.UInt32] $mockSmbShare.ConcurrentUserLimit
                                EncryptData           = $mockSmbShare.EncryptData
                                FolderEnumerationMode = $mockSmbShare.FolderEnumerationMode
                                CachingMode           = $mockSmbShare.CachingMode
                                # Property that is not in desired state.
                                ContinuouslyAvailable = $false
                                ShareState            = $mockSmbShare.ShareState
                                ShareType             = $mockSmbShare.ShareType
                                ShadowCopy            = $mockSmbShare.ShadowCopy
                                Special               = $mockSmbShare.Special
                                FullAccess            = [System.String[]] $mockFullPermissionUserName
                                ChangeAccess          = [System.String[]] $mockChangePermissionUserName
                                ReadAccess            = [System.String[]] $mockReadPermissionUserName
                                NoAccess              = [System.String[]] $mockNoPermissionUserName
                                Ensure                = 'Present'
                            }
                        }
                    }

                    It 'Should call the correct mocks' {
                        $setTargetResourceParameters = @{
                            Name                  = $mockShareName
                            Path                  = 'TestDrive:\Temp'
                            Description           = 'Some description'
                            ConcurrentUserLimit   = 2
                            EncryptData           = $false
                            FolderEnumerationMode = 'AccessBased'
                            CachingMode           = 'Manual'
                            ContinuouslyAvailable = $true
                            ChangeAccess          = $mockChangePermissionUserName
                            ReadAccess            = $mockReadPermissionUserName
                            FullAccess            = $mockFullPermissionUserName
                            NoAccess              = $mockNoPermissionUserName
                            Verbose               = $true
                        }

                        { Set-TargetResource @setTargetResourceParameters } | Should -Not -Throw

                        Assert-MockCalled Set-SmbShare -Exactly -Times 1 -Scope It
                        Assert-MockCalled Remove-SmbShareAccessPermission -Exactly -Times 1 -Scope It
                        Assert-MockCalled Add-SmbShareAccessPermission -Exactly -Times 1 -Scope It
                        Assert-MockCalled New-SmbShare -Exactly -Times 0 -Scope It
                        Assert-MockCalled Remove-SmbShare -Exactly -Times 0 -Scope It
                    }
                }
            }
        }

        Describe 'MSFT_SmbShare\Test-TargetResource' -Tag 'Test' {
            Context 'When the system is not in the desired state' {
                Context 'When no member are provided in any of the access permission collections' {
                    BeforeAll {
                        $testTargetResourceParameters = @{
                            Name                  = $mockShareName
                            Path                  = 'TestDrive:\Temp'
                            FullAccess            = @()
                            ChangeAccess          = @()
                            ReadAccess            = @()
                            NoAccess              = @()
                            Ensure                = 'Present'
                            Verbose               = $true
                        }
                    }

                    It 'Should throw the correct error' {
                        {
                            Test-TargetResource @testTargetResourceParameters
                        } | Should -Throw $script:localizedData.WrongAccessParameters
                    }
                }

                Context 'When there is a configured SMB share' {
                    BeforeAll {
                        $mockDefaultTestCaseValues = @{
                            TestCase              = ''
                            Name                  = $mockSmbShare.Name
                            Path                  = $mockSmbShare.Path
                            Description           = $mockSmbShare.Description
                            ConcurrentUserLimit   = $mockSmbShare.ConcurrentUserLimit
                            EncryptData           = $mockSmbShare.EncryptData
                            FolderEnumerationMode = $mockSmbShare.FolderEnumerationMode
                            CachingMode           = $mockSmbShare.CachingMode
                            ContinuouslyAvailable = $mockSmbShare.ContinuouslyAvailable
                            FullAccess            = @()
                            ChangeAccess          = @()
                            ReadAccess            = @($mockReadPermissionUserName)
                            NoAccess              = @()
                            Ensure                = 'Present'
                        }

                        $mockTestCase1 = $mockDefaultTestCaseValues.Clone()
                        $testProperty = 'Path'
                        $mockTestCase1['TestCase'] = $testProperty
                        $mockTestCase1[$testProperty] = 'TestDrive:\NewFolder'

                        $mockTestCase2 = $mockDefaultTestCaseValues.Clone()
                        $testProperty = 'Description'
                        $mockTestCase2['TestCase'] = $testProperty
                        $mockTestCase2[$testProperty] = 'New description'

                        $mockTestCase3 = $mockDefaultTestCaseValues.Clone()
                        $testProperty = 'ConcurrentUserLimit'
                        $mockTestCase3['TestCase'] = $testProperty
                        $mockTestCase3[$testProperty] = 2

                        $mockTestCase4 = $mockDefaultTestCaseValues.Clone()
                        $testProperty = 'EncryptData'
                        $mockTestCase4['TestCase'] = $testProperty
                        $mockTestCase4[$testProperty] = $true

                        $mockTestCase5 = $mockDefaultTestCaseValues.Clone()
                        $testProperty = 'FolderEnumerationMode'
                        $mockTestCase5['TestCase'] = $testProperty
                        $mockTestCase5[$testProperty] = 'Unrestricted'

                        $mockTestCase6 = $mockDefaultTestCaseValues.Clone()
                        $testProperty = 'CachingMode'
                        $mockTestCase6['TestCase'] = $testProperty
                        $mockTestCase6[$testProperty] = 'Documents'

                        $mockTestCase7 = $mockDefaultTestCaseValues.Clone()
                        $testProperty = 'ContinuouslyAvailable'
                        $mockTestCase7['TestCase'] = $testProperty
                        $mockTestCase7[$testProperty] = $false

                        $mockTestCase8 = $mockDefaultTestCaseValues.Clone()
                        $testProperty = 'FullAccess'
                        $mockTestCase8['TestCase'] = $testProperty
                        $mockTestCase8[$testProperty] = @('NewUser')

                        $mockTestCase9 = $mockDefaultTestCaseValues.Clone()
                        $testProperty = 'ChangeAccess'
                        $mockTestCase9['TestCase'] = $testProperty
                        $mockTestCase9[$testProperty] = @('NewUser')

                        $mockTestCase10 = $mockDefaultTestCaseValues.Clone()
                        $testProperty = 'ReadAccess'
                        $mockTestCase10['TestCase'] = $testProperty
                        $mockTestCase10[$testProperty] = @('NewUser')

                        $mockTestCase11 = $mockDefaultTestCaseValues.Clone()
                        $testProperty = 'NoAccess'
                        $mockTestCase11['TestCase'] = $testProperty
                        $mockTestCase11[$testProperty] = @('NewUser')

                        $testCases = @(
                            $mockTestCase1
                            $mockTestCase2
                            $mockTestCase3
                            $mockTestCase4
                            $mockTestCase5
                            $mockTestCase6
                            $mockTestCase7
                            $mockTestCase8
                            $mockTestCase9
                            $mockTestCase10
                            $mockTestCase11
                        )

                        Mock -CommandName Get-TargetResource -MockWith {
                            return @{
                                Name                  = $mockSmbShare.Name
                                Path                  = $mockSmbShare.Path
                                Description           = $mockSmbShare.Description
                                ConcurrentUserLimit   = [System.UInt32] $mockSmbShare.ConcurrentUserLimit
                                EncryptData           = $mockSmbShare.EncryptData
                                FolderEnumerationMode = $mockSmbShare.FolderEnumerationMode
                                CachingMode           = $mockSmbShare.CachingMode
                                ContinuouslyAvailable = $mockSmbShare.ContinuouslyAvailable
                                ShareState            = $mockSmbShare.ShareState
                                ShareType             = $mockSmbShare.ShareType
                                ShadowCopy            = $mockSmbShare.ShadowCopy
                                Special               = $mockSmbShare.Special
                                FullAccess            = [System.String[]] @()
                                ChangeAccess          = [System.String[]] @()
                                ReadAccess            = [System.String[]] @()
                                NoAccess              = [System.String[]] @()
                                Ensure                = 'Present'
                            }
                        }
                    }

                    It 'Should return $false when property <TestCase> has the wrong value' -TestCases $testCases {
                        param
                        (
                            $Name,
                            $Path,
                            $Description,
                            $ConcurrentUserLimit,
                            $EncryptData,
                            $FolderEnumerationMode,
                            $CachingMode,
                            $ContinuouslyAvailable,
                            $FullAccess,
                            $ChangeAccess,
                            $ReadAccess,
                            $NoAccess,
                            $Ensure
                        )

                        $testTargetResourceParameters = @{
                            Name                  = $Name
                            Path                  = $Path
                            Description           = $Description
                            ConcurrentUserLimit   = $ConcurrentUserLimit
                            EncryptData           = $EncryptData
                            FolderEnumerationMode = $FolderEnumerationMode
                            CachingMode           = $CachingMode
                            ContinuouslyAvailable = $ContinuouslyAvailable
                            FullAccess            = $FullAccess
                            ChangeAccess          = $ChangeAccess
                            ReadAccess            = $ReadAccess
                            NoAccess              = $NoAccess
                            Ensure                = 'Present'
                            Verbose               = $true
                        }

                        $testTargetResourceResult = Test-TargetResource @testTargetResourceParameters
                        $testTargetResourceResult | Should -BeFalse
                    }

                    It 'Should return $false when the desired state should be ''Absent''' {
                        $testTargetResourceParameters = @{
                            Ensure                = 'Absent'
                            Name                  = $mockSmbShare.Name
                            Path                  = $mockSmbShare.Path
                            Description           = $mockSmbShare.Description
                            ConcurrentUserLimit   = [System.UInt32] $mockSmbShare.ConcurrentUserLimit
                            EncryptData           = $mockSmbShare.EncryptData
                            FolderEnumerationMode = $mockSmbShare.FolderEnumerationMode
                            CachingMode           = $mockSmbShare.CachingMode
                            ContinuouslyAvailable = $mockSmbShare.ContinuouslyAvailable
                            FullAccess            = @()
                            ChangeAccess          = @()
                            ReadAccess            = @($mockReadPermissionUserName)
                            NoAccess              = @()
                            Verbose               = $true
                        }

                        $testTargetResourceResult = Test-TargetResource @testTargetResourceParameters
                        $testTargetResourceResult | Should -BeFalse
                    }
                }

                Context 'When there are no configured SMB share' {
                    BeforeAll {
                        Mock -CommandName Get-TargetResource -MockWith {
                            return @{
                                Ensure = 'Absent'
                            }
                        }
                    }

                    It 'Should return $false when the desired state should ''Present''' {
                        $testTargetResourceParameters = @{
                            Ensure  = 'Present'
                            Name    = $mockSmbShare.Name
                            Path    = $mockSmbShare.Path
                            Verbose = $true
                        }

                        $testTargetResourceResult = Test-TargetResource @testTargetResourceParameters
                        $testTargetResourceResult | Should -BeFalse
                    }
                }
            }

            Context 'When the system is in the desired state' {
                Context 'When there is a configured SMB share' {
                    BeforeAll {
                        Mock -CommandName Get-TargetResource -MockWith {
                            return @{
                                Name                  = $mockSmbShare.Name
                                Path                  = $mockSmbShare.Path
                                Description           = $mockSmbShare.Description
                                ConcurrentUserLimit   = [System.UInt32] $mockSmbShare.ConcurrentUserLimit
                                EncryptData           = $mockSmbShare.EncryptData
                                FolderEnumerationMode = $mockSmbShare.FolderEnumerationMode
                                CachingMode           = $mockSmbShare.CachingMode
                                ContinuouslyAvailable = $mockSmbShare.ContinuouslyAvailable
                                ShareState            = $mockSmbShare.ShareState
                                ShareType             = $mockSmbShare.ShareType
                                ShadowCopy            = $mockSmbShare.ShadowCopy
                                Special               = $mockSmbShare.Special
                                FullAccess            = [System.String[]] @()
                                ChangeAccess          = [System.String[]] @()
                                ReadAccess            = [System.String[]] @($mockReadPermissionUserName)
                                NoAccess              = [System.String[]] @()
                                Ensure                = 'Present'
                            }
                        }
                    }

                    It 'Should return $true when the desired state should be ''Present''' {
                        $testTargetResourceParameters = @{
                            Ensure                = 'Present'
                            Name                  = $mockSmbShare.Name
                            Path                  = $mockSmbShare.Path
                            Description           = $mockSmbShare.Description
                            ConcurrentUserLimit   = [System.UInt32] $mockSmbShare.ConcurrentUserLimit
                            EncryptData           = $mockSmbShare.EncryptData
                            FolderEnumerationMode = $mockSmbShare.FolderEnumerationMode
                            CachingMode           = $mockSmbShare.CachingMode
                            ContinuouslyAvailable = $mockSmbShare.ContinuouslyAvailable
                            FullAccess            = @()
                            ChangeAccess          = @()
                            ReadAccess            = @($mockReadPermissionUserName)
                            NoAccess              = @()
                            Verbose               = $true
                        }

                        $testTargetResourceResult = Test-TargetResource @testTargetResourceParameters
                        $testTargetResourceResult | Should -BeTrue
                    }
                }

                Context 'When there are no configured SMB share' {
                    BeforeAll {
                        Mock -CommandName Get-TargetResource -MockWith {
                            return @{
                                Ensure = 'Absent'
                            }
                        }
                    }

                    It 'Should return $true when the desired state should ''Absent''' {
                        $testTargetResourceParameters = @{
                            Ensure  = 'Absent'
                            Name    = $mockSmbShare.Name
                            Path    = $mockSmbShare.Path
                            Verbose = $true
                        }

                        $testTargetResourceResult = Test-TargetResource @testTargetResourceParameters
                        $testTargetResourceResult | Should -BeTrue
                    }
                }
            }
        }

        Describe 'MSFT_SmbShare\Add-SmbShareAccessPermission' -Tag 'Helper' {
            BeforeAll {
                Mock -CommandName Grant-SmbShareAccess
                Mock -CommandName Block-SmbShareAccess

                Mock -CommandName Get-SmbShareAccess -MockWith {
                    <#
                        Mocked permission:
 
                        Full = @('User3', 'User4')
                        Change = @('User1')
                        Read = @('User2')
                        Denied = @('DeniedUser1')
                    #>

                    return $mockSmbShareAccess
                }
            }

            Context 'When adding granted permissions to an SMB share' {
                BeforeAll {
                    $mockExpectedAccountToBeAdded = 'NewUser'
                }

                AfterEach {
                    Assert-MockCalled -CommandName Block-SmbShareAccess -Exactly -Times 0 -Scope 'It'
                }

                Context 'When an account with full access should be added' {
                    BeforeAll {
                        $addSmbShareAccessPermissionParameters = @{
                            Name       = $mockShareName
                            # User3 is an already present account. It should not be added.
                            FullAccess = @('User3', $mockExpectedAccountToBeAdded)
                            Verbose    = $true
                        }
                    }

                    It 'Should not throw an error and call the correct mocks' {
                        { Add-SmbShareAccessPermission @addSmbShareAccessPermissionParameters } | Should -Not -Throw

                        <#
                            Assert that Grant-SmbShareAccess is only called once, and
                            that only time was with the correct parameters.
                        #>

                        Assert-MockCalled -CommandName Grant-SmbShareAccess -Exactly -Times 1 -Scope 'It'
                        Assert-MockCalled -CommandName Grant-SmbShareAccess -ParameterFilter {
                            $Name -eq $mockShareName `
                                -and $AccessRight -eq 'Full' `
                                -and $AccountName -eq $mockExpectedAccountToBeAdded
                        } -Exactly -Times 1 -Scope 'It'
                    }
                }

                Context 'When an account with change access should be added' {
                    BeforeAll {
                        $addSmbShareAccessPermissionParameters = @{
                            Name         = $mockShareName
                            # User1 is an already present account. It should not be added.
                            ChangeAccess = @('User1', $mockExpectedAccountToBeAdded)
                            Verbose      = $true
                        }
                    }

                    It 'Should not throw an error and call the correct mocks' {
                        { Add-SmbShareAccessPermission @addSmbShareAccessPermissionParameters } | Should -Not -Throw

                        <#
                            Assert that Grant-SmbShareAccess is only called once, and
                            that only time was with the correct parameters.
                        #>

                        Assert-MockCalled -CommandName Grant-SmbShareAccess -Exactly -Times 1 -Scope 'It'
                        Assert-MockCalled -CommandName Grant-SmbShareAccess -ParameterFilter {
                            $Name -eq $mockShareName `
                                -and $AccessRight -eq 'Change' `
                                -and $AccountName -eq $mockExpectedAccountToBeAdded
                        } -Exactly -Times 1 -Scope 'It'
                    }
                }

                Context 'When an account with read access should be added' {
                    BeforeAll {
                        $addSmbShareAccessPermissionParameters = @{
                            Name       = $mockShareName
                            # User2 is an already present account. It should not be added.
                            ReadAccess = @('User2', $mockExpectedAccountToBeAdded)
                            Verbose    = $true
                        }
                    }

                    It 'Should not throw an error and call the correct mocks' {
                        { Add-SmbShareAccessPermission @addSmbShareAccessPermissionParameters } | Should -Not -Throw

                        <#
                            Assert that Grant-SmbShareAccess is only called once, and
                            that only time was with the correct parameters.
                        #>

                        Assert-MockCalled -CommandName Grant-SmbShareAccess -Exactly -Times 1 -Scope 'It'
                        Assert-MockCalled -CommandName Grant-SmbShareAccess -ParameterFilter {
                            $Name -eq $mockShareName `
                                -and $AccessRight -eq 'Read' `
                                -and $AccountName -eq $mockExpectedAccountToBeAdded
                        } -Exactly -Times 1 -Scope 'It'
                    }
                }

                Context 'When accounts with different access should be added' {
                    BeforeAll {
                        $mockExpectedAccountToBeAdded1 = 'NweUser1'
                        $mockExpectedAccountToBeAdded2 = 'NweUser2'
                        $mockExpectedAccountToBeAdded3 = 'NweUser3'

                        $addSmbShareAccessPermissionParameters = @{
                            Name         = $mockShareName
                            # User1, User2, and User3 is an already present account. It should not be added.
                            FullAccess   = @('User3', $mockExpectedAccountToBeAdded1)
                            ReadAccess   = @('User2', $mockExpectedAccountToBeAdded2)
                            ChangeAccess = @('User1', $mockExpectedAccountToBeAdded3)
                            Verbose      = $true
                        }
                    }

                    It 'Should not throw an error and call the correct mocks' {
                        { Add-SmbShareAccessPermission @addSmbShareAccessPermissionParameters } | Should -Not -Throw

                        <#
                            Assert that Grant-SmbShareAccess is only called once, and
                            that only time was with the correct parameters.
                        #>

                        Assert-MockCalled -CommandName Grant-SmbShareAccess -Exactly -Times 3 -Scope 'It'
                        Assert-MockCalled -CommandName Grant-SmbShareAccess -ParameterFilter {
                            $Name -eq $mockShareName `
                                -and $AccessRight -eq 'Change' `
                                -and $AccountName -eq $mockExpectedAccountToBeAdded3
                        } -Exactly -Times 1 -Scope 'It'

                        Assert-MockCalled -CommandName Grant-SmbShareAccess -ParameterFilter {
                            $Name -eq $mockShareName `
                                -and $AccessRight -eq 'Full' `
                                -and $AccountName -eq $mockExpectedAccountToBeAdded1
                        } -Exactly -Times 1 -Scope 'It'

                        Assert-MockCalled -CommandName Grant-SmbShareAccess -ParameterFilter {
                            $Name -eq $mockShareName `
                                -and $AccessRight -eq 'Read' `
                                -and $AccountName -eq $mockExpectedAccountToBeAdded2
                        } -Exactly -Times 1 -Scope 'It'
                    }
                }
            }

            Context 'When denying permissions on an SMB share' {
                AfterEach {
                    Assert-MockCalled -CommandName Grant-SmbShareAccess -Exactly -Times 0 -Scope 'It'
                }

                Context 'When an account with denied access should be revoked' {
                    BeforeAll {
                        $mockExpectedAccountToBeBlocked = 'NewDeniedUser'

                        $removeSmbShareAccessPermissionParameters = @{
                            Name     = $mockShareName
                            NoAccess = @('DeniedUser1', $mockExpectedAccountToBeBlocked)
                            Verbose  = $true
                        }
                    }

                    It 'Should not throw an error and call the correct mocks' {
                        { Add-SmbShareAccessPermission @removeSmbShareAccessPermissionParameters } | Should -Not -Throw

                        <#
                            Assert that Block-SmbShareAccess is only called once, and
                            that only time was with the correct parameters.
                        #>

                        Assert-MockCalled -CommandName Block-SmbShareAccess -Exactly -Times 1 -Scope 'It'
                        Assert-MockCalled -CommandName Block-SmbShareAccess -ParameterFilter {
                            $Name -eq $mockShareName `
                                -and $AccountName -eq $mockExpectedAccountToBeBlocked
                        } -Exactly -Times 1 -Scope 'It'
                    }
                }
            }
        }

        Describe 'MSFT_SmbShare\Remove-SmbShareAccessPermission' -Tag 'Helper' {
            BeforeAll {
                Mock -CommandName Revoke-SmbShareAccess
                Mock -CommandName Unblock-SmbShareAccess

                Mock -CommandName Get-SmbShareAccess -MockWith {
                    <#
                        Mocked permission:
 
                        Full = @('User3', 'User4')
                        Change = @('User1')
                        Read = @('User2')
                        Denied = @('DeniedUser1')
                    #>

                    return $mockSmbShareAccess
                }
            }

            Context 'When revoking granted permissions from an SMB share' {
                AfterEach {
                    Assert-MockCalled -CommandName Unblock-SmbShareAccess -Exactly -Times 0 -Scope 'It'
                }

                Context 'When an account with full access should be removed' {
                    BeforeAll {
                        $mockExpectedAccountToBeRemoved = 'User4'

                        $removeSmbShareAccessPermissionParameters = @{
                            Name       = $mockShareName
                            FullAccess = @('User3')
                            Verbose    = $true
                        }
                    }

                    It 'Should not throw an error and call the correct mocks' {
                        { Remove-SmbShareAccessPermission @removeSmbShareAccessPermissionParameters } | Should -Not -Throw

                        <#
                            Assert that Revoke-SmbShareAccess is only called once, and
                            that only time was with the correct parameters.
                        #>

                        Assert-MockCalled -CommandName Revoke-SmbShareAccess -Exactly -Times 1 -Scope 'It'
                        Assert-MockCalled -CommandName Revoke-SmbShareAccess -ParameterFilter {
                            $Name -eq $mockShareName `
                                -and $AccountName -eq $mockExpectedAccountToBeRemoved
                        } -Exactly -Times 1 -Scope 'It'
                    }
                }

                Context 'When an all accounts with full access should be removed' {
                    BeforeAll {
                        $mockExpectedAccountToBeRemoved1 = 'User3'
                        $mockExpectedAccountToBeRemoved2 = 'User4'

                        $removeSmbShareAccessPermissionParameters = @{
                            Name       = $mockShareName
                            FullAccess = @()
                            Verbose    = $true
                        }
                    }

                    It 'Should not throw an error and call the correct mocks' {
                        { Remove-SmbShareAccessPermission @removeSmbShareAccessPermissionParameters } | Should -Not -Throw

                        <#
                            Assert that Revoke-SmbShareAccess is called twice, and
                            that both times it is called with the correct parameters.
                        #>

                        Assert-MockCalled -CommandName Revoke-SmbShareAccess -Exactly -Times 2 -Scope 'It'
                        Assert-MockCalled -CommandName Revoke-SmbShareAccess -ParameterFilter {
                            $Name -eq $mockShareName `
                                -and $AccountName -eq $mockExpectedAccountToBeRemoved1
                        } -Exactly -Times 1 -Scope 'It'

                        Assert-MockCalled -CommandName Revoke-SmbShareAccess -ParameterFilter {
                            $Name -eq $mockShareName `
                                -and $AccountName -eq $mockExpectedAccountToBeRemoved2
                        } -Exactly -Times 1 -Scope 'It'
                    }
                }

                Context 'When an account with change access should be removed' {
                    BeforeAll {
                        $mockExpectedAccountToBeRemoved = 'User1'

                        $removeSmbShareAccessPermissionParameters = @{
                            Name         = $mockShareName
                            ChangeAccess = @()
                            Verbose      = $true
                        }
                    }

                    It 'Should not throw an error and call the correct mocks' {
                        { Remove-SmbShareAccessPermission @removeSmbShareAccessPermissionParameters } | Should -Not -Throw

                        <#
                            Assert that Revoke-SmbShareAccess is only called once, and
                            that only time was with the correct parameters.
                        #>

                        Assert-MockCalled -CommandName Revoke-SmbShareAccess -Exactly -Times 1 -Scope 'It'
                        Assert-MockCalled -CommandName Revoke-SmbShareAccess -ParameterFilter {
                            $Name -eq $mockShareName `
                                -and $AccountName -eq $mockExpectedAccountToBeRemoved
                        } -Exactly -Times 1 -Scope 'It'
                    }
                }

                Context 'When an account with read access should be removed' {
                    BeforeAll {
                        $mockExpectedAccountToBeRemoved = 'User2'

                        $removeSmbShareAccessPermissionParameters = @{
                            Name       = $mockShareName
                            ReadAccess = @()
                            Verbose    = $true
                        }
                    }

                    It 'Should not throw an error and call the correct mocks' {
                        { Remove-SmbShareAccessPermission @removeSmbShareAccessPermissionParameters } | Should -Not -Throw

                        <#
                            Assert that Revoke-SmbShareAccess is only called for each account,
                            and each time with the correct parameters.
                        #>

                        Assert-MockCalled -CommandName Revoke-SmbShareAccess -Exactly -Times 1 -Scope 'It'
                        Assert-MockCalled -CommandName Revoke-SmbShareAccess -ParameterFilter {
                            $Name -eq $mockShareName `
                                -and $AccountName -eq $mockExpectedAccountToBeRemoved
                        } -Exactly -Times 1 -Scope 'It'


                    }
                }

                Context 'When an all granted access should be removed' {
                    BeforeAll {
                        $removeSmbShareAccessPermissionParameters = @{
                            Name         = $mockShareName
                            FullAccess   = @()
                            ChangeAccess = @()
                            ReadAccess   = @()
                            Verbose      = $true
                        }
                    }

                    It 'Should not throw an error and call the correct mocks' {
                        { Remove-SmbShareAccessPermission @removeSmbShareAccessPermissionParameters } | Should -Not -Throw

                        Assert-MockCalled -CommandName Revoke-SmbShareAccess -Exactly -Times 4 -Scope 'It'
                        Assert-MockCalled -CommandName Revoke-SmbShareAccess -ParameterFilter {
                            $Name -eq $mockShareName `
                                -and $AccountName -eq 'User1'
                        } -Exactly -Times 1 -Scope 'It'

                        Assert-MockCalled -CommandName Revoke-SmbShareAccess -ParameterFilter {
                            $Name -eq $mockShareName `
                                -and $AccountName -eq 'User2'
                        } -Exactly -Times 1 -Scope 'It'

                        Assert-MockCalled -CommandName Revoke-SmbShareAccess -ParameterFilter {
                            $Name -eq $mockShareName `
                                -and $AccountName -eq 'User3'
                        } -Exactly -Times 1 -Scope 'It'

                        Assert-MockCalled -CommandName Revoke-SmbShareAccess -ParameterFilter {
                            $Name -eq $mockShareName `
                                -and $AccountName -eq 'User4'
                        } -Exactly -Times 1 -Scope 'It'
                    }
                }
            }

            Context 'When revoking denied permissions from an SMB share' {
                AfterEach {
                    Assert-MockCalled -CommandName Revoke-SmbShareAccess -Exactly -Times 0 -Scope 'It'
                }

                Context 'When an account with denied access should be revoked' {
                    BeforeAll {
                        $mockExpectedAccountToBeUnblocked = 'DeniedUser1'

                        $removeSmbShareAccessPermissionParameters = @{
                            Name     = $mockShareName
                            NoAccess = @()
                            Verbose  = $true
                        }
                    }

                    It 'Should not throw an error and call the correct mocks' {
                        { Remove-SmbShareAccessPermission @removeSmbShareAccessPermissionParameters } | Should -Not -Throw

                        <#
                            Assert that Block-SmbShareAccess is only called once, and
                            that only time was with the correct parameters.
                        #>

                        Assert-MockCalled -CommandName Unblock-SmbShareAccess -Exactly -Times 1 -Scope 'It'
                        Assert-MockCalled -CommandName Unblock-SmbShareAccess -ParameterFilter {
                            $Name -eq $mockShareName `
                                -and $AccountName -eq $mockExpectedAccountToBeUnblocked
                        } -Exactly -Times 1 -Scope 'It'
                    }
                }
            }
        }

        Describe 'MSFT_SmbShare\Assert-AccessPermissionParameters' -Tag 'Helper' {
            Context 'When asserting correct provided access permissions parameters' {
                Context 'When providing at least one member in one of the access permission collections' {
                    BeforeAll {
                        $testCases = @(
                            @{
                                TestCase     = 'FullAccess'
                                FullAccess   = @('Member1')
                                ChangeAccess = @()
                                ReadAccess   = @()
                                NoAccess     = @()
                            },
                            @{
                                TestCase     = 'ChangeAccess'
                                FullAccess   = @()
                                ChangeAccess = @('Member1')
                                ReadAccess   = @()
                                NoAccess     = @()
                            },
                            @{
                                TestCase     = 'ReadAccess'
                                FullAccess   = @()
                                ChangeAccess = @()
                                ReadAccess   = @('Member1')
                                NoAccess     = @()
                            },
                            @{
                                TestCase     = 'NoAccess'
                                FullAccess   = @()
                                ChangeAccess = @()
                                ReadAccess   = @('Member1')
                                NoAccess     = @()
                            }
                        )
                    }

                    It 'Should not throw an error when testing a member in <TestCase>' -TestCases $testCases {
                        param
                        (
                            $FullAccess,
                            $ChangeAccess,
                            $ReadAccess,
                            $NoAccess
                        )

                        # We must using splatting to test 'ValueFromRemainingArguments' parameter.
                        $assertAccessPermissionParameters = @{
                            FullAccess     = $FullAccess
                            ChangeAccess   = $ChangeAccess
                            ReadAccess     = $ReadAccess
                            NoAccess       = $NoAccess
                            DummyParameter = 'Testing ValueFromRemainingArguments'
                        }

                        {
                            Assert-AccessPermissionParameters @assertAccessPermissionParameters
                        } | Should -Not -Throw
                    }
                }

                Context 'When not providing any members in any of the access permission collections' {
                    It 'Should throw the correct error' {
                        # We must using splatting to test 'ValueFromRemainingArguments' parameter.
                        $assertAccessPermissionParameters = @{
                            FullAccess     = @()
                            ChangeAccess   = @()
                            ReadAccess     = @()
                            NoAccess       = @()
                            DummyParameter = 'Testing ValueFromRemainingArguments'
                        }

                        {
                            Assert-AccessPermissionParameters @assertAccessPermissionParameters
                        } | Should -Throw $script:localizedData.WrongAccessParameters
                    }
                }
            }
        }
    }
}
finally
{
    Invoke-TestCleanup
}