Tests/Get-ADLocalDC.Tests.ps1

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

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

    . $sPath

    Function Get-ADComputerSite {}

    Function Get-ADDomain {}
}

Describe "Get-ADLocalDC" {
    Context "Should return DC1" {
        BeforeAll {
            mock Get-ADComputerSite { return "NoSuchSite" }
            mock Get-ADDomainControllersBySite { return @(@{Name="DC1.mydomain.com"},@{Name="DC2.mydomain.com"}) }
            mock Get-ADDomainControllerDirectoryEntry {
                return [PSCustomObject] @{
                    defaultNamingContext = $true
                    DCName = "DC1.mydomain.com"
                }
            }
        }

        It "Should return DC1" {
            Get-ADLocalDC | Should -Be "DC1.mydomain.com"
        }
    }

    Context "Should return DC2" {
        BeforeAll {
            mock Get-ADComputerSite { return "NoSuchSite" }
            mock Get-ADDomainControllersBySite { return @(@{Name="DC1.mydomain.com"},@{Name="DC2.mydomain.com"}) }
            mock Get-ADDomainControllerDirectoryEntry {
                if ($sDirectoryEntryPath -eq "LDAP://DC2.mydomain.com/RootDSE") {
                    return [PSCustomObject] @{
                        defaultNamingContext = $true
                        DCName = "DC2.mydomain.com"
                    }
                }
                else {
                    return $null
                }
            }
        }

        It "Should return DC2" {
            Get-ADLocalDC | Should -Be "DC2.mydomain.com"
        }
    }

    Context "No site returned" {
        BeforeAll {
            mock Get-ADComputerSite { throw "Site not available"}
        }

        It "Should return 'Site not available'" {
            try {
                Get-ADLocalDC
            }
            catch {
                $Error[0].Exception.Message | Should -Be 'Site not available'
            }
        }
    }

    Context "Should return NO DCs" {
        BeforeAll {
            mock Get-ADComputerSite { return "NoSuchSite" }
            mock Get-ADDomainControllersBySite { return $null }
        }

        It "Should return error" {
            try {
                Get-ADLocalDC | Should -Be "DC2.mydomain.com"
            }
            catch {
                $Error[0].Exception.Message | Should -Be 'Failed to discover any domain controllers'
            }
        }
    }

    Context "Test with Get-ADDomain cmdlet" {
        BeforeAll {
            mock Get-ADComputerSite { return "NoSuchSite" }
            mock Get-ADDomainControllersBySite { return @(@{Name="DC1.mydomain.com"},@{Name="DC2.mydomain.com"}) }
            mock Get-ADDomainControllerDirectoryEntry {
                return [PSCustomObject] @{
                    defaultNamingContext = $true
                    DCName = "DC1.mydomain.com"
                }
            }
            mock Get-ADDomain { 
                return [PSCustomObject] @{
                    DNSDomain = "mydomain.com"
                }
            }
        }

        It "Should return DC1" {
            Get-ADLocalDC -UsePsAdCommand | Should -Be "DC1.mydomain.com"
        }
    }

    Context "Get-ADDomain cmdlet not available" {
        BeforeAll {
            mock Get-ADComputerSite { return "NoSuchSite" }
            mock Get-ADDomainControllersBySite { return @(@{Name="DC1.mydomain.com"},@{Name="DC2.mydomain.com"}) }
            mock Get-ADDomain { Throw "Command not available: Get-ADDomain" }
        }

        It "Should return an error" {
            try {
                Get-ADLocalDC -UsePsAdCommand
            }
            catch {
                $Error[0].Exception.Message | Should -Match ".*Command not available: Get-ADDomain.*"
            }
        }
    }    
}

AfterAll {
    Remove-Item function:\Get-ADDomain
    Remove-Item function:\Get-ADComputerSite
}