. $PSScriptRoot\..\..\Load-PesterModules.ps1 $here = Split-Path -Parent $MyInvocation.MyCommand.Path $sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.tests\.', '.' $functionPath = Join-Path -Path $here -ChildPath $sut Write-Host "Overriding SUT: $functionPath" Import-Module $functionPath -Force $moduleForMock = "" Describe "Clear-GMSAPasswords" { Context "Error Handling" { It "Writes a Warning and Returns if No Services Found" { Mock -CommandName Get-ChocolateyServices -MockWith { return @() } -ModuleName $moduleForMock Mock -CommandName Get-AlkamiServices -MockWith { return @() } -ModuleName $moduleForMock Mock -CommandName Write-Warning -MockWith {} -ModuleName $moduleForMock Mock -CommandName Get-WindowsServiceUser -MockWith {} -ModuleName $moduleForMock Mock -CommandName Invoke-SCExe -MockWith {} -ModuleName $moduleForMock Mock -CommandName Set-ServiceAccountManagedState -MockWith {} -ModuleName $moduleForMock Clear-GMSAPasswords # Assert the Warning is Written Assert-MockCalled -CommandName Write-Warning -Times 1 -Exactly -Scope It -ModuleName $moduleForMock -ParameterFilter { $Message -match "Found no Services" } # Assert No Calls to Invoke-SCExe are made when no services are found Assert-MockCalled -CommandName Invoke-SCExe -Times 0 -Exactly -Scope It -ModuleName $moduleForMock } It "Writes a Warning and Skips Services Not Running as GMSA Accounts" { Mock -CommandName Get-ChocolateyServices -MockWith { return @( New-Object PSObject -Property @{ Name="Super.Fake.Awesome.Service"; } ) } -ModuleName $moduleForMock Mock -CommandName Get-AlkamiServices -MockWith { return @( New-Object PSObject -Property @{ Name="Other.Fake.Awesome.Nag.Service"; } ) } -ModuleName $moduleForMock Mock -CommandName Get-WindowsServiceUser -MockWith { return "FH\fake.User" } -ModuleName $moduleForMock Mock -CommandName Write-Warning -MockWith {} -ModuleName $moduleForMock Mock -CommandName Invoke-SCExe -MockWith {} -ModuleName $moduleForMock Mock -CommandName Set-ServiceAccountManagedState -MockWith {} -ModuleName $moduleForMock Clear-GMSAPasswords # Assert that a warning is written for both Choco and Legacy services Assert-MockCalled -CommandName Write-Warning -Times 2 -Exactly -Scope It -ModuleName $moduleForMock -ParameterFilter { $Message -match "Skipping Service" } # Assert No Calls to Invoke-SCExe are made when no services are found running under gMSA context Assert-MockCalled -CommandName Invoke-SCExe -Times 0 -Exactly -Scope It -ModuleName $moduleForMock } It "Writes a Warning if Services Were Found But None Match the Filter List Parameter" { Mock -CommandName Get-ChocolateyServices -MockWith { return @( New-Object PSObject -Property @{ Name="Super.Fake.Awesome.Service"; } ) } -ModuleName $moduleForMock Mock -CommandName Get-AlkamiServices -MockWith { return @( New-Object PSObject -Property @{ Name="Super.Fake.Radium.Service"; } ) } -ModuleName $moduleForMock Mock -CommandName Write-Warning -MockWith {} -ModuleName $moduleForMock Mock -CommandName Invoke-SCExe -MockWith {} -ModuleName $moduleForMock Mock -CommandName Set-ServiceAccountManagedState -MockWith {} -ModuleName $moduleForMock Clear-GMSAPasswords "NonExistent Service!" # Assert that a warning is written because no services are found matching the supplied filter Assert-MockCalled -CommandName Write-Warning -Times 1 -Exactly -Scope It -ModuleName $moduleForMock -ParameterFilter { $Message -match "Found no matching services" } # Assert No Calls to Invoke-SCExe are made when no matching services are found Assert-MockCalled -CommandName Invoke-SCExe -Times 0 -Exactly -Scope It -ModuleName $moduleForMock } } Context "External Calls" { It "Calls Set-ServiceAccountManagedState for Each Service When No Service Filter Supplied" { Mock -CommandName Get-WindowsServiceUser -MockWith { return "FH\fake.User$" } -ModuleName $moduleForMock Mock -CommandName Get-AlkamiServices -MockWith { return @() } -ModuleName $moduleForMock Mock -CommandName Invoke-SCExe -MockWith {} -ModuleName $moduleForMock Mock -CommandName Write-Verbose -MockWith {} -ModuleName $moduleForMock Mock -CommandName Set-ServiceAccountManagedState -MockWith {} -ModuleName $moduleForMock Mock -CommandName Get-ChocolateyServices -ModuleName $moduleForMock -MockWith { return @( (New-Object PSObject -Property @{ Name="Super.Fake.Awesome.Service"; }), (New-Object PSObject -Property @{ Name="NotSoSuper.Fake.Sucky.Service"; }) ) } Clear-GMSAPasswords # Make sure Set-ServiceAccountManagedState was called for each service Assert-MockCalled -CommandName Set-ServiceAccountManagedState -Times 2 -Exactly -Scope It # Make sure Set-ServiceAccountManagedState was called with the expected service name filters Assert-MockCalled -CommandName Set-ServiceAccountManagedState -Times 1 -Exactly -Scope It -ModuleName $moduleForMock ` -ParameterFilter { $ServiceName -match "Super.Fake.Awesome.Service" } Assert-MockCalled -CommandName Set-ServiceAccountManagedState -Times 1 -Exactly -Scope It -ModuleName $moduleForMock ` -ParameterFilter { $ServiceName -match "NotSoSuper.Fake.Sucky.Service" } } It "Correctly Filters Set-ServiceAccountManagedState Based on a Supplied Service Name String" { Mock -CommandName Get-WindowsServiceUser -MockWith { return "FH\fake.User$" } -ModuleName $moduleForMock Mock -CommandName Get-AlkamiServices -MockWith { return @() } -ModuleName $moduleForMock Mock -CommandName Invoke-SCExe -MockWith {} -ModuleName $moduleForMock Mock -CommandName Write-Verbose -MockWith {} -ModuleName $moduleForMock Mock -CommandName Set-ServiceAccountManagedState -MockWith {} -ModuleName $moduleForMock Mock -CommandName Get-ChocolateyServices -ModuleName $moduleForMock -MockWith { return @( (New-Object PSObject -Property @{ Name="Super.Fake.Awesome.Service"; }), (New-Object PSObject -Property @{ Name="NotSoSuper.Fake.Sucky.Service"; }) ) } Clear-GMSAPasswords "Super.Fake.Awesome.Service" # Make sure Set-ServiceAccountManagedState was only called once Assert-MockCalled -CommandName Set-ServiceAccountManagedState -Times 1 -Exactly -Scope It # Make sure Set-ServiceAccountManagedState was called with the expected service name filter Assert-MockCalled -CommandName Set-ServiceAccountManagedState -Times 1 -Exactly -Scope It -ModuleName $moduleForMock ` -ParameterFilter { $ServiceName -match "Super.Fake.Awesome.Service" } } } Context "Parameter Handling" { It "Correctly Filters Based on a Supplied Service Name String" { Mock -CommandName Get-WindowsServiceUser -MockWith { return "FH\fake.User$" } -ModuleName $moduleForMock Mock -CommandName Get-AlkamiServices -MockWith { return @() } -ModuleName $moduleForMock Mock -CommandName Invoke-SCExe -MockWith {} -ModuleName $moduleForMock Mock -CommandName Write-Verbose -MockWith {} -ModuleName $moduleForMock Mock -CommandName Set-ServiceAccountManagedState -MockWith {} -ModuleName $moduleForMock Mock -CommandName Get-ChocolateyServices -ModuleName $moduleForMock -MockWith { return @( (New-Object PSObject -Property @{ Name="Super.Fake.Awesome.Service"; }), (New-Object PSObject -Property @{ Name="NotSoSuper.Fake.Sucky.Service"; }) ) } Clear-GMSAPasswords "Super.Fake.Awesome.Service" -Verbose # Assert that Invoke-SCExe is only called once due to the supplied service name filter Assert-MockCalled -CommandName Invoke-SCExe -Times 1 -Exactly -Scope It -ModuleName $moduleForMock # Make sure Invoke-SCExe was called with the expected service name filter Assert-MockCalled -CommandName Invoke-SCExe -Times 1 -Exactly -Scope It -ModuleName $moduleForMock ` -ParameterFilter { $Arguments -contains "Super.Fake.Awesome.Service" } # Assert that we write a verbose message indicating the other service was skipped Assert-MockCalled -CommandName Write-Verbose -Times 1 -Exactly -Scope It -ModuleName $moduleForMock -ParameterFilter { $Message -match "Skipping Service NotSoSuper.Fake.Sucky.Service" } } It "Correctly Filters Based on a Service Name Array" { Mock -CommandName Get-WindowsServiceUser -MockWith { return "FH\fake.User$" } -ModuleName $moduleForMock Mock -CommandName Get-AlkamiServices -MockWith { return @() } -ModuleName $moduleForMock Mock -CommandName Invoke-SCExe -MockWith {} -ModuleName $moduleForMock Mock -CommandName Write-Verbose -MockWith {} -ModuleName $moduleForMock Mock -CommandName Set-ServiceAccountManagedState -MockWith {} -ModuleName $moduleForMock Mock -CommandName Get-ChocolateyServices -ModuleName $moduleForMock -MockWith { return @( (New-Object PSObject -Property @{ Name="Super.Fake.Awesome.Service"; }), (New-Object PSObject -Property @{ Name="Yet.Another.Awesome.Service"; }), (New-Object PSObject -Property @{ Name="NotSoSuper.Fake.Sucky.Service"; }) ) } Clear-GMSAPasswords @("Super.Fake.Awesome.Service","Yet.Another.Awesome.Service") -Verbose # Assert that Invoke-SCExe was called twice for both services in the array param Assert-MockCalled -CommandName Invoke-SCExe -Times 2 -Exactly -Scope It -ModuleName $moduleForMock # Make sure Invoke-SCExe was called with the expected service name filter Assert-MockCalled -CommandName Invoke-SCExe -Times 1 -Exactly -Scope It -ModuleName $moduleForMock ` -ParameterFilter { $Arguments -contains "Super.Fake.Awesome.Service" } Assert-MockCalled -CommandName Invoke-SCExe -Times 1 -Exactly -Scope It -ModuleName $moduleForMock ` -ParameterFilter { $Arguments -contains "Yet.Another.Awesome.Service" } # Assert that we write a verbose message indicating the other service was skipped Assert-MockCalled -CommandName Write-Verbose -Times 1 -Exactly -Scope It -ModuleName $moduleForMock -ParameterFilter { $Message -match "Skipping Service NotSoSuper.Fake.Sucky.Service" } } It "Only Acts on Unique Service Names Once" { Mock -CommandName Get-WindowsServiceUser -MockWith { return "FH\fake.User$" } -ModuleName $moduleForMock Mock -CommandName Invoke-SCExe -MockWith {} -ModuleName $moduleForMock Mock -CommandName Write-Verbose -MockWith {} -ModuleName $moduleForMock Mock -CommandName Set-ServiceAccountManagedState -MockWith {} -ModuleName $moduleForMock Mock -CommandName Get-AlkamiServices -ModuleName $moduleForMock -MockWith { return New-Object PSObject -Property @{ Name="Super.Fake.Awesome.Service"; } } Mock -CommandName Get-ChocolateyServices -ModuleName $moduleForMock -MockWith { return New-Object PSObject -Property @{ Name="Super.Fake.Awesome.Service"; } } Clear-GMSAPasswords @("Super.Fake.Awesome.Service") # Assert that Invoke-SCExe is only called once though the same service name was returned by both # Get-AlkamiServices and Get-ChocolateyServices Assert-MockCalled -CommandName Invoke-SCExe -Times 1 -Exactly -Scope It -ModuleName $moduleForMock } } }