. $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 = "" #region Enable-Service-Unit Describe "Enable-Service-Unit" -Tag 'Unit' { Context "Logic" { #region Arrange $randomFileName = [System.IO.Path]::GetRandomFileName() $testServiceName = ("_FAKE{0}" -f ($randomFileName.Split(".") | Select-Object -First 1)) Write-Warning ("Using Test Service Name '{0}'" -f $testServiceName) Write-Host "Creating Test Service $testServiceName" $svc = New-Service -Name $testServiceName -BinaryPathName "FakePath" -StartupType "Disabled" $svc = Get-Service $testServiceName -ErrorAction SilentlyContinue # Write warnings as part of this function if setting the service fails, but since we don't actually change the service # type in the Set-Service mock the warnings always fire in the tests. So just suprress them here. Mock -CommandName Write-Host -MockWith { } -ModuleName $moduleForMock Mock -CommandName Write-Warning -MockWith { } -ModuleName $moduleForMock Mock -CommandName Set-Service -MockWith { } -ModuleName $moduleForMock <# Pester `Mock -MockWith` is ... weird. It lets you use parameter variable names from *inside* the scope of the namespace you're mocking the command call *from*. So $service.Name below is not evaluated until the call to Get-Service from *inside* of Alkami.PowerShell.Services happens. At which point, $service has a value, as does $service.Name https://github.com/pester/Pester/wiki/Mock - where they describe the `Mock-With` parameter. #> Mock -CommandName Get-Service -MockWith { [PSCustomObject]@{ Name = $service.Name; StartType = "Disabled"; Status = "Stopped" } } -ModuleName $moduleForMock if ($null -eq $svc){ Set-ItResult -Inconclusive -Because 'Could not create service fake' } #endregion Arrange It "Calls Set-Service with Disabled Service" { #region Act Enable-Service $svc #endregion Act #region Assert Assert-MockCalled -ModuleName $moduleForMock -CommandName Set-Service -ParameterFilter { $Name -eq $testServiceName -and $StartupType -eq "Manual" } -Scope It -Exactly 1 #endregion Assert } It "Calls Set-Service with an Auto Service" { Mock -CommandName Get-Service -MockWith { [PSCustomObject]@{ Name = $service.Name; StartType = "Automatic"; Status = "Stopped" } } -ModuleName $moduleForMock #region Act Enable-Service $svc #endregion Act #region Assert Assert-MockCalled -ModuleName $moduleForMock -CommandName Set-Service -ParameterFilter { $Name -eq $testServiceName -and $StartupType -eq "Manual" } -Scope It -Exactly 1 #endregion Assert } It "Calls Invoke-SCExe with a Tier-0 service"{ Mock -CommandName Get-Service -MockWith { [PSCustomObject]@{ Name = $service.Name; StartType = "Disabled"; Status = "Stopped" } } -ModuleName $moduleForMock Mock -CommandName Invoke-SCExe -MockWith { } -ModuleName $moduleForMock Mock -CommandName Get-ServicesByTier -MockWith { return $service.Name } -ModuleName $moduleForMock #region Act Enable-Service $svc #endregion Act #region Assert Assert-MockCalled -ModuleName $moduleForMock -CommandName Invoke-SCExe -Scope It -Exactly 1 #endregion Assert } It "Calls Set-Service with a Manual Service" { Mock -CommandName Get-Service -MockWith { [PSCustomObject]@{ Name = $service.Name; StartType = "Manual"; Status = "Stopped" } } -ModuleName $moduleForMock Mock -CommandName Get-ServicesByTier -MockWith { } -ModuleName $moduleForMock #region Act Enable-Service $svc #endregion Act #region Assert Assert-MockCalled -ModuleName $moduleForMock -CommandName Set-Service -ParameterFilter { $Name -eq $testServiceName -and $StartupType -eq "Manual" } -Scope It -Exactly 0 #endregion Assert # Multiple tests use the service, only clean up in the last one. #region Cleanup (Get-CIMInstance Win32_Service -filter ("name='{0}'" -f $testServiceName)) | Invoke-CIMMethod -MethodName Delete #endregion Cleanup } } } #endregion Enable-Service-Unit