Tests/Unit/MSFT_SqlDatabaseDefaultLocation.Tests.ps1
<#
.SYNOPSIS Automated unit test for MSFT_SqlDatabaseDefaultLocation DSC resource. .NOTES To run this script locally, please make sure to first run the bootstrap script. Read more at https://github.com/PowerShell/SqlServerDsc/blob/dev/CONTRIBUTING.md#bootstrap-script-assert-testenvironment #> Import-Module -Name (Join-Path -Path $PSScriptRoot -ChildPath '..\TestHelpers\CommonTestHelper.psm1') if (Test-SkipContinuousIntegrationTask -Type 'Unit') { return } $script:dscModuleName = 'SqlServerDsc' $script:dscResourceName = 'MSFT_SqlDatabaseDefaultLocation' #region Header # Unit Test Template Version: 1.2.1 $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 ` -TestType Unit #endregion HEADER function Invoke-TestSetup { # Loading mocked classes Add-Type -Path (Join-Path -Path (Join-Path -Path $PSScriptRoot -ChildPath 'Stubs') -ChildPath 'SMO.cs') # Importing SQLPS stubs Import-Module -Name (Join-Path -Path (Join-Path -Path $PSScriptRoot -ChildPath 'Stubs') -ChildPath 'SQLPSStub.psm1') -Force -Global } function Invoke-TestCleanup { Restore-TestEnvironment -TestEnvironment $TestEnvironment } # Begin Testing try { Invoke-TestSetup InModuleScope $script:dscResourceName { $mockServerName = 'localhost' $mockInstanceName = 'MSSQLSERVER' $mockSQLDataPath = 'C:\Program Files\Data\' $mockSqlLogPath = 'C:\Program Files\Log\' # Ending backslash is regression test for issue #1307. $mockSqlBackupPath = 'C:\Program Files\Backup\' $mockSqlAlterDataPath = 'C:\Program Files\' $mockSqlAlterLogPath = 'C:\Program Files\' $mockSqlAlterBackupPath = 'C:\Program Files\' $mockRestartService = $true $mockExpectedAlterDataPath = $env:temp $mockExpectedAlterLogPath = $env:temp $mockExpectedAlterBackupPath = $env:temp $mockInvalidPathForData = 'C:\InvalidPath' $mockInvalidPathForLog = 'C:\InvalidPath' $mockInvalidPathForBackup = 'C:\InvalidPath' $mockInvalidOperationForAlterMethod = $false $mockProcessOnlyOnActiveNode = $true $script:WasMethodAlterCalled = $false #region Function mocks # Default parameters that are used for the It-blocks $mockDefaultParameters = @{ InstanceName = $mockInstanceName ServerName = $mockServerName } $mockConnectSQL = { return New-Object -TypeName Microsoft.SqlServer.Management.Smo.Server | Add-Member -MemberType NoteProperty -Name InstanceName -Value $mockInstanceName -PassThru -Force | Add-Member -MemberType NoteProperty -Name ComputerNamePhysicalNetBIOS -Value $mockServerName -PassThru -Force | Add-Member -MemberType NoteProperty -Name DefaultFile -Value $mockSqlDataPath -PassThru -Force | Add-Member -MemberType NoteProperty -Name DefaultLog -Value $mockSqlLogPath -PassThru -Force | # Ending backslash is removed because of regression test for issue #1307. Add-Member -MemberType NoteProperty -Name BackupDirectory -Value $mockSqlBackupPath.TrimEnd('\') -PassThru -Force | Add-Member -MemberType ScriptMethod -Name Alter -Value { if ($mockInvalidOperationForAlterMethod) { throw 'Mock Alter Method was called with invalid operation.' } $script:WasMethodAlterCalled = $true } -PassThru -Force } #endregion Describe 'MSFT_SqlDatabaseDefaultLocation\Get-TargetResource' -Tag 'Get' { BeforeAll { $testCases = @( @{ Type = 'Data' Path = $mockSqlDataPath }, @{ Type = 'Log' Path = $mockSqlLogPath }, @{ Type = 'Backup' # Ending backslash is removed because of regression test for issue #1307. Path = $mockSqlBackupPath.TrimEnd('\') } ) } BeforeEach { Mock -CommandName Connect-SQL -MockWith $mockConnectSQL -Verifiable Mock -CommandName Test-ActiveNode -MockWith { param ( [PSObject] $ServerObject ) return $true } -Verifiable } Context 'When the system is either in the desired state or not in the desired state' { It 'Should get the default path for <Type> with the value <Path>' -TestCases $testCases { param ( $Type, $Path ) $getTargetResourceResult = Get-TargetResource @mockDefaultParameters -Type $Type -Path $Path $getTargetResourceResult.Path | Should -Be $Path $getTargetResourceResult.Type | Should -Be $Type $getTargetResourceResult.ServerName | Should -Be $mockDefaultParameters.ServerName $getTargetResourceResult.InstanceName | Should -Be $mockDefaultParameters.InstanceName Assert-MockCalled Connect-SQL -Exactly -Times 1 -Scope It } } } Describe 'MSFT_SqlDatabaseDefaultLocation\Test-TargetResource' -Tag 'Test' { BeforeAll { $testCases = @( @{ Type = 'Data' Path = $mockSqlDataPath AlterPath = $mockSqlAlterDataPath }, @{ Type = 'Log' Path = $mockSqlLogPath AlterPath = $mockSqlAlterLogPath }, @{ Type = 'Backup' Path = $mockSqlBackupPath AlterPath = $mockSqlAlterBackupPath } ) } BeforeEach { Mock -CommandName Connect-SQL -MockWith $mockConnectSQL -Verifiable Mock -CommandName Test-ActiveNode -MockWith { $mockProcessOnlyOnActiveNode } -Verifiable } Context 'When the system is in the desired state.' { It 'Should return true when the desired state of the <Type> path has the value <Path>' -TestCases $testCases { param ( $Type, $Path ) $testTargetResourceResult = Test-TargetResource @mockDefaultParameters -Type $Type -Path $Path $testTargetResourceResult | Should -Be $true Assert-MockCalled Connect-SQL -Exactly -Times 1 -Scope It } } Context 'When the system is not in the desired state.' { It 'Should return false when the desired state of the <Type> path does not equal <Path>' -TestCases $testCases { param ( $Type, $Path, $AlterPath ) $testTargetResourceResult = Test-TargetResource @mockDefaultParameters -Type $Type -Path $AlterPath $testTargetResourceResult | Should -Be $false Assert-MockCalled Connect-SQL -Exactly -Times 1 -Scope It } } Context 'When the ProcessOnlyOnActiveNode parameter is passed' { AfterAll { $mockProcessOnlyOnActiveNode = $mockProcessOnlyOnActiveNodeOriginal } BeforeAll { $mockProcessOnlyOnActiveNodeOriginal = $mockProcessOnlyOnActiveNode $mockProcessOnlyOnActiveNode = $false } It 'Should be "true" when ProcessOnlyOnActiveNode is <mockProcessOnlyOnActiveNode>.' { $testTargetResourceParameters = $mockDefaultParameters $testTargetResourceParameters += @{ Path = $mockSqlDataPath Type = 'Data' ProcessOnlyOnActiveNode = $mockProcessOnlyOnActiveNode } Test-TargetResource @testTargetResourceParameters | Should -Be $true Assert-MockCalled -CommandName Connect-SQL -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Test-ActiveNode -Scope It -Times 1 -Exactly } It 'Should be "true" when ProcessOnlyOnActiveNode is <mockProcessOnlyOnActiveNodeOriginal>.' { $testTargetResourceParameters = $mockDefaultParameters $testTargetResourceParameters += @{ Path = $mockSqlDataPath Type = 'Data' ProcessOnlyOnActiveNode = $mockProcessOnlyOnActiveNodeOriginal } Test-TargetResource @testTargetResourceParameters | Should -Be $true Assert-MockCalled -CommandName Connect-SQL -Scope It -Times 1 -Exactly Assert-MockCalled -CommandName Test-ActiveNode -Scope It -Times 1 -Exactly } } } Describe 'MSFT_SqlDatabaseDefaultLocation\Set-TargetResource' -Tag 'Set' { BeforeAll { $testCases = @( @{ Type = 'Data' Path = $mockSqlDataPath AlterPath = $mockSqlAlterDataPath ExpectedAlterPath = $mockExpectedAlterDataPath InvalidPath = $mockInvalidPathForData }, @{ Type = 'Log' Path = $mockSqlLogPath AlterPath = $mockSqlAlterLogPath ExpectedAlterPath = $mockExpectedAlterLogPath InvalidPath = $mockInvalidPathForLog }, @{ Type = 'Backup' Path = $mockSqlBackupPath AlterPath = $mockSqlAlterBackupPath ExpectedAlterPath = $mockExpectedAlterBackupPath InvalidPath = $mockInvalidPathForBackup } ) } BeforeEach { Mock -CommandName Connect-SQL -MockWith $mockConnectSQL -Verifiable Mock -CommandName Restart-SqlService -Verifiable # This is used to evaluate if mocked Alter() method was called. $script:WasMethodAlterCalled = $false } Context 'When the system is not in the desired state.' { It 'Should not throw when the path is successfully changed.' -TestCases $testCases { param ( $Type, $Path, $AlterPath ) $setTargetResourceParameters = @{ Type = $Type Path = $AlterPath RestartService = $mockRestartService } {Set-TargetResource @mockDefaultParameters @setTargetResourceParameters} | Should -Not -Throw $script:WasMethodAlterCalled | Should -Be $true Assert-MockCalled Connect-SQL -Exactly -Times 1 -Scope It Assert-MockCalled Restart-SqlService -Exactly -Times 1 -Scope It } It 'Should throw when the path is invalid.' -TestCases $testCases { param ( $Type, $InvalidPath ) $setTargetResourceParameters = @{ Type = $Type Path = $InvalidPath RestartService = $mockRestartService } $throwInvalidPath = "The path '$InvalidPath' does not exist." {Set-TargetResource @mockDefaultParameters @setTargetResourceParameters} | Should -Throw $throwInvalidPath $script:WasMethodAlterCalled | Should -Be $false Assert-MockCalled Connect-SQL -Exactly -Times 0 -Scope It Assert-MockCalled Restart-SqlService -Exactly -Times 0 -Scope It } } $mockInvalidOperationForAlterMethod = $true It 'Should throw the correct error when Alter() method was called with invalid operation' -TestCases $testCases { param ( $Type, $Path, $AlterPath, $ExpectedAlterPath ) $throwInvalidOperation = "Changing the default path failed." $setTargetResourceParameters = @{ Type = $Type Path = $ExpectedAlterPath RestartService = $mockRestartService } {Set-TargetResource @mockDefaultParameters @setTargetResourceParameters} | Should -Throw $throwInvalidOperation Assert-MockCalled Connect-SQL -Exactly -Times 1 -Scope It Assert-MockCalled Restart-SqlService -Exactly -Times 0 -Scope It } } } } finally { Invoke-TestCleanup } |