Tests/Get-ADAvailableDomainController.Tests.ps1

[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseDeclaredVarsMoreThanAssignments", "")]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingConvertToSecureStringWithPlainText")]
param()

BeforeAll {
    # Import the script file
    $sPath = ($PSScriptRoot).Replace("Tests","Public") + "\Get-ADAvailableDomainController.ps1"

    . $sPath
}

Describe "Get-ADAvailableDomainController" {
    Context "Normal operation - no credential required" {
        BeforeAll {
            Mock Resolve-DnsName { return @{ NameTarget = @("DC1.mydomain.com","DC2.mydomain.com") ; Type="SRV" } }
            Mock New-Object { return [PSCustomObject]@{ defaultNamingContext = "ABC" } }
        }

        It "Should return DC1" {
            Get-ADAvailableDomainController -DnsDomainName "mydomain.com" | Should -Be "dc1.mydomain.com"
        }
    }

    Context "Normal operation - with credential" {
        BeforeAll {
            $objCred = New-Object PSCredential -ArgumentList "UserName",("Password" | ConvertTo-SecureString -AsPlainText -Force)
            Mock Resolve-DnsName { return @{ NameTarget = @("DC1.mydomain.com","DC2.mydomain.com") ; Type="SRV" } }
            Mock New-Object { return [PSCustomObject]@{ defaultNamingContext = "ABC" } }
        }

        It "Should return DC1" {
            Get-ADAvailableDomainController -DnsDomainName "mydomain.com" -DomainCredential $objCred | Should -Be "dc1.mydomain.com"
        }
    }

    Context "Test with single DC returned" {
        BeforeAll {
            Mock Resolve-DnsName { return @{ NameTarget = @("DC2.mydomain.com") ; Type="SRV" } }
            Mock New-Object { return [PSCustomObject]@{ defaultNamingContext = "ABC" } }
        }

        It "Should return DC2" {
            Get-ADAvailableDomainController -DnsDomainName "mydomain.com" | Should -Be "dc2.mydomain.com"
        }
    }

    Context "Fail DNS lookup" {
        BeforeAll {
            Mock Resolve-DnsName { throw "Target does not exist" }
        }

        It "Should throw error on DNS lookup" {
            try {
                Get-ADAvailableDomainController -DnsDomainName "mydomain.com"
            }
            catch {
                $Error[0].Exception.Message | Should -BeLike "Failed to perform DNS lookup on SRV record*"
            }
        }
    }

    Context "No Domain Controllers returned by DNS lookup" {
        BeforeAll {
            Mock Resolve-DnsName { return $null }
        }

        It "Should throw error on DNS lookup" {
            try {
                Get-ADAvailableDomainController -DnsDomainName "mydomain.com"
            }
            catch {
                $Error[0].Exception.Message | Should -BeLike "Failed to discover an available Domain Controller*"
            }
        }
    }


    Context "AD lookup fails for all servers" {
        BeforeAll {
            Mock Resolve-DnsName { return @{ NameTarget = @("DC2.mydomain.com") ; Type="SRV" } }
            Mock New-Object { return [PSCustomObject]@{ someData = "ABC" } }
        }

        It "Should throw error on DNS lookup" {
            try {
                Get-ADAvailableDomainController -DnsDomainName "mydomain.com"
            }
            catch {
                $Error[0].Exception.Message | Should -BeLike "Failed to access to a Domain Controller for mydomain.com*"
            }
        }
    }

    Context "Cleartext password variable does not exist after execution" {
        BeforeAll {
            $objCred = New-Object PSCredential -ArgumentList "UserName",("Password" | ConvertTo-SecureString -AsPlainText -Force)
            Mock Resolve-DnsName { return @{ NameTarget = @("DC1.mydomain.com") ; Type="SRV" } }
            Mock New-Object { return [PSCustomObject]@{ defaultNamingContext = "ABC" } }

            $sDC = Get-ADAvailableDomainController -DnsDomainName "mydomain.com" -DomainCredential $objCred
        }

        It "Should throw error on DNS lookup failure" {
            try {
                Get-Variable -Name sPwdClear -ErrorAction "Stop"
            }
            catch {
                $Error[0].Exception.Message | Should -Be "Cannot find a variable with the name 'sPwdClear'."
            }
        }
    }
}