Skip to content

Commit 65a1f9a

Browse files
authored
Add integration test for Invoke-SqlDscQuery command (#2256)
1 parent e3c32b5 commit 65a1f9a

File tree

4 files changed

+249
-0
lines changed

4 files changed

+249
-0
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1313
- Added integration tests for `Remove-SqlDscAudit` command to ensure it functions
1414
correctly in real environments
1515
[issue #2241](https://github.com/dsccommunity/SqlServerDsc/issues/2241).
16+
- Added integration tests for `Invoke-SqlDscQuery` command to ensure it functions
17+
correctly in real environments
18+
[issue #2227](https://github.com/dsccommunity/SqlServerDsc/issues/2227).
1619
- Added integration tests for `New-SqlDscAudit` command to ensure it functions
1720
correctly in real environments
1821
[issue #2226](https://github.com/dsccommunity/SqlServerDsc/issues/2226).

azure-pipelines.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,7 @@ stages:
325325
'tests/Integration/Commands/New-SqlDscDatabase.Integration.Tests.ps1'
326326
'tests/Integration/Commands/Set-SqlDscDatabase.Integration.Tests.ps1'
327327
'tests/Integration/Commands/Test-SqlDscDatabase.Integration.Tests.ps1'
328+
'tests/Integration/Commands/Invoke-SqlDscQuery.Integration.Tests.ps1'
328329
'tests/Integration/Commands/Set-SqlDscDatabasePermission.Integration.Tests.ps1'
329330
'tests/Integration/Commands/ConvertTo-SqlDscDatabasePermission.Integration.Tests.ps1'
330331
'tests/Integration/Commands/Get-SqlDscAgentAlert.Integration.Tests.ps1'
Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'Suppressing this rule because Script Analyzer does not understand Pester syntax.')]
2+
param ()
3+
4+
BeforeDiscovery {
5+
try
6+
{
7+
if (-not (Get-Module -Name 'DscResource.Test'))
8+
{
9+
# Assumes dependencies have been resolved, so if this module is not available, run 'noop' task.
10+
if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable))
11+
{
12+
# Redirect all streams to $null, except the error stream (stream 2)
13+
& "$PSScriptRoot/../../../build.ps1" -Tasks 'noop' 3>&1 4>&1 5>&1 6>&1 > $null
14+
}
15+
16+
# If the dependencies have not been resolved, this will throw an error.
17+
Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop'
18+
}
19+
}
20+
catch [System.IO.FileNotFoundException]
21+
{
22+
throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks noop" first.'
23+
}
24+
}
25+
26+
BeforeAll {
27+
$script:moduleName = 'SqlServerDsc'
28+
29+
Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop'
30+
}
31+
32+
Describe 'Invoke-SqlDscQuery' -Tag @('Integration_SQL2017', 'Integration_SQL2019', 'Integration_SQL2022') {
33+
BeforeAll {
34+
# Starting the named instance SQL Server service prior to running tests.
35+
Start-Service -Name 'MSSQL$DSCSQLTEST' -Verbose -ErrorAction 'Stop'
36+
37+
$script:mockInstanceName = 'DSCSQLTEST'
38+
$script:mockComputerName = Get-ComputerName
39+
40+
$mockSqlAdministratorUserName = 'SqlAdmin' # Using computer name as NetBIOS name throw exception.
41+
$mockSqlAdministratorPassword = ConvertTo-SecureString -String 'P@ssw0rd1' -AsPlainText -Force
42+
43+
$script:mockSqlAdminCredential = [System.Management.Automation.PSCredential]::new($mockSqlAdministratorUserName, $mockSqlAdministratorPassword)
44+
45+
$script:serverObject = Connect-SqlDscDatabaseEngine -InstanceName $script:mockInstanceName -Credential $script:mockSqlAdminCredential
46+
47+
# Create a test database for our queries
48+
$script:testDatabaseName = 'SqlDscTestInvokeQuery_' + (Get-Random)
49+
$null = New-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -Force -ErrorAction 'Stop'
50+
51+
# Create a test table with some data
52+
$createTableQuery = @"
53+
CREATE TABLE TestTable (
54+
ID int IDENTITY(1,1) PRIMARY KEY,
55+
Name nvarchar(50),
56+
Value int
57+
)
58+
59+
INSERT INTO TestTable (Name, Value) VALUES ('Test1', 100), ('Test2', 200), ('Test3', 300)
60+
"@
61+
62+
Invoke-SqlDscQuery -ServerObject $script:serverObject -DatabaseName $script:testDatabaseName -Query $createTableQuery -Force -ErrorAction 'Stop'
63+
}
64+
65+
AfterAll {
66+
# Clean up test database
67+
if ($script:testDatabaseName)
68+
{
69+
try
70+
{
71+
Remove-SqlDscDatabase -ServerObject $script:serverObject -Name $script:testDatabaseName -Force -ErrorAction 'Stop'
72+
}
73+
catch
74+
{
75+
Write-Warning -Message "Failed to remove test database '$($script:testDatabaseName)': $($_.Exception.Message)"
76+
}
77+
}
78+
79+
Disconnect-SqlDscDatabaseEngine -ServerObject $script:serverObject
80+
81+
# Stop the named instance SQL Server service to save memory on the build worker.
82+
Stop-Service -Name 'MSSQL$DSCSQLTEST' -Verbose -ErrorAction 'Stop'
83+
}
84+
85+
Context 'When executing a query using ServerObject parameter set' {
86+
Context 'When executing a query without returning results' {
87+
It 'Should execute the query without throwing (using Force parameter)' {
88+
{
89+
Invoke-SqlDscQuery -ServerObject $script:serverObject -DatabaseName $script:testDatabaseName -Query 'UPDATE TestTable SET Value = 500 WHERE ID = 1' -Force -ErrorAction 'Stop'
90+
} | Should -Not -Throw
91+
}
92+
93+
It 'Should execute the query without throwing (using Confirm:$false parameter)' {
94+
{
95+
Invoke-SqlDscQuery -ServerObject $script:serverObject -DatabaseName $script:testDatabaseName -Query 'UPDATE TestTable SET Value = 600 WHERE ID = 2' -Confirm:$false -ErrorAction 'Stop'
96+
} | Should -Not -Throw
97+
}
98+
}
99+
100+
Context 'When executing a query with PassThru parameter' {
101+
It 'Should return results when using PassThru parameter' {
102+
$result = Invoke-SqlDscQuery -ServerObject $script:serverObject -DatabaseName $script:testDatabaseName -Query 'SELECT * FROM TestTable' -PassThru -Force -ErrorAction 'Stop'
103+
104+
$result | Should -Not -BeNullOrEmpty
105+
$result | Should -BeOfType 'System.Data.DataSet'
106+
$result.Tables[0].Rows.Count | Should -BeGreaterOrEqual 3
107+
}
108+
109+
It 'Should return specific results when querying with WHERE clause' {
110+
$result = Invoke-SqlDscQuery -ServerObject $script:serverObject -DatabaseName $script:testDatabaseName -Query "SELECT Name FROM TestTable WHERE Name = 'Test1'" -PassThru -Force -ErrorAction 'Stop'
111+
112+
$result | Should -Not -BeNullOrEmpty
113+
$result | Should -BeOfType 'System.Data.DataSet'
114+
$result.Tables[0].Rows.Count | Should -Be 1
115+
$result.Tables[0].Rows[0]['Name'] | Should -Be 'Test1'
116+
}
117+
}
118+
119+
Context 'When using optional parameters with ServerObject parameter set' {
120+
It 'Should execute query with custom StatementTimeout' {
121+
{
122+
Invoke-SqlDscQuery -ServerObject $script:serverObject -DatabaseName $script:testDatabaseName -Query 'SELECT COUNT(*) FROM TestTable' -StatementTimeout 30 -PassThru -Force -ErrorAction 'Stop'
123+
} | Should -Not -Throw
124+
}
125+
126+
It 'Should execute query with RedactText parameter' {
127+
{
128+
Invoke-SqlDscQuery -ServerObject $script:serverObject -DatabaseName $script:testDatabaseName -Query "SELECT * FROM TestTable WHERE Name = 'SensitiveData'" -RedactText @('SensitiveData') -PassThru -Force -ErrorAction 'Stop'
129+
} | Should -Not -Throw
130+
}
131+
}
132+
133+
Context 'When accepting ServerObject from pipeline' {
134+
It 'Should execute query when ServerObject is passed through pipeline' {
135+
$result = $script:serverObject | Invoke-SqlDscQuery -DatabaseName $script:testDatabaseName -Query 'SELECT COUNT(*) as RecordCount FROM TestTable' -PassThru -Force -ErrorAction 'Stop'
136+
137+
$result | Should -Not -BeNullOrEmpty
138+
$result | Should -BeOfType 'System.Data.DataSet'
139+
$result.Tables[0].Rows[0]['RecordCount'] | Should -BeGreaterOrEqual 3
140+
}
141+
}
142+
}
143+
144+
Context 'When executing a query using ByServerName parameter set' {
145+
Context 'When executing a query without returning results' {
146+
It 'Should execute the query without throwing' {
147+
{
148+
Invoke-SqlDscQuery -ServerName $script:mockComputerName -InstanceName $script:mockInstanceName -Credential $script:mockSqlAdminCredential -DatabaseName $script:testDatabaseName -Query 'UPDATE TestTable SET Value = 700 WHERE ID = 3' -Force -ErrorAction 'Stop'
149+
} | Should -Not -Throw
150+
}
151+
}
152+
153+
Context 'When executing a query with PassThru parameter' {
154+
It 'Should return results when using PassThru parameter' {
155+
$result = Invoke-SqlDscQuery -ServerName $script:mockComputerName -InstanceName $script:mockInstanceName -Credential $script:mockSqlAdminCredential -DatabaseName $script:testDatabaseName -Query 'SELECT Name, Value FROM TestTable ORDER BY ID' -PassThru -Force -ErrorAction 'Stop'
156+
157+
$result | Should -Not -BeNullOrEmpty
158+
$result | Should -BeOfType 'System.Data.DataSet'
159+
$result.Tables[0].Rows.Count | Should -BeGreaterOrEqual 3
160+
}
161+
}
162+
163+
Context 'When using optional parameters with ByServerName parameter set' {
164+
# Using Encrypt in the CI is not possible until we add the required support (certificate) in the CI.
165+
It 'Should execute query with Encrypt parameter' -Skip {
166+
{
167+
Invoke-SqlDscQuery -ServerName $script:mockComputerName -InstanceName $script:mockInstanceName -Credential $script:mockSqlAdminCredential -DatabaseName $script:testDatabaseName -Query 'SELECT 1 as TestValue' -Encrypt -PassThru -Force -ErrorAction 'Stop'
168+
} | Should -Not -Throw
169+
}
170+
171+
It 'Should execute query with LoginType parameter' {
172+
# Create SQL Server credential for 'sa' login
173+
$sqlLoginPassword = ConvertTo-SecureString -String 'P@ssw0rd1' -AsPlainText -Force
174+
$sqlLoginCredential = [System.Management.Automation.PSCredential]::new('sa', $sqlLoginPassword)
175+
176+
{
177+
Invoke-SqlDscQuery -ServerName $script:mockComputerName -InstanceName $script:mockInstanceName -Credential $sqlLoginCredential -LoginType 'SqlLogin' -DatabaseName $script:testDatabaseName -Query 'SELECT 1 as TestValue' -PassThru -Force -ErrorAction 'Stop'
178+
} | Should -Not -Throw
179+
}
180+
181+
It 'Should execute query with custom StatementTimeout' {
182+
{
183+
Invoke-SqlDscQuery -ServerName $script:mockComputerName -InstanceName $script:mockInstanceName -Credential $script:mockSqlAdminCredential -DatabaseName $script:testDatabaseName -Query 'SELECT 1 as TestValue' -StatementTimeout 60 -PassThru -Force -ErrorAction 'Stop'
184+
} | Should -Not -Throw
185+
}
186+
}
187+
}
188+
189+
Context 'When testing error handling' {
190+
It 'Should throw error when querying non-existent database' {
191+
{
192+
Invoke-SqlDscQuery -ServerObject $script:serverObject -DatabaseName 'NonExistentDatabase' -Query 'SELECT 1' -Force -ErrorAction 'Stop'
193+
} | Should -Throw
194+
}
195+
196+
It 'Should throw error when executing invalid SQL query' {
197+
{
198+
Invoke-SqlDscQuery -ServerObject $script:serverObject -DatabaseName $script:testDatabaseName -Query 'INVALID SQL SYNTAX' -Force -ErrorAction 'Stop'
199+
} | Should -Throw
200+
}
201+
202+
It 'Should throw error when querying non-existent table' {
203+
{
204+
Invoke-SqlDscQuery -ServerObject $script:serverObject -DatabaseName $script:testDatabaseName -Query 'SELECT * FROM NonExistentTable' -Force -ErrorAction 'Stop'
205+
} | Should -Throw
206+
}
207+
}
208+
209+
Context 'When testing system databases' {
210+
It 'Should execute query against master database' {
211+
$result = Invoke-SqlDscQuery -ServerObject $script:serverObject -DatabaseName 'master' -Query 'SELECT name FROM sys.databases WHERE name = ''master''' -PassThru -Force -ErrorAction 'Stop'
212+
213+
$result | Should -Not -BeNullOrEmpty
214+
$result | Should -BeOfType 'System.Data.DataSet'
215+
$result.Tables[0].Rows.Count | Should -Be 1
216+
$result.Tables[0].Rows[0]['name'] | Should -Be 'master'
217+
}
218+
219+
It 'Should execute query against msdb database' {
220+
$result = Invoke-SqlDscQuery -ServerObject $script:serverObject -DatabaseName 'msdb' -Query 'SELECT COUNT(*) as TableCount FROM INFORMATION_SCHEMA.TABLES' -PassThru -Force -ErrorAction 'Stop'
221+
222+
$result | Should -Not -BeNullOrEmpty
223+
$result | Should -BeOfType 'System.Data.DataSet'
224+
$result.Tables[0].Rows[0]['TableCount'] | Should -BeGreaterThan 0
225+
}
226+
}
227+
228+
Context 'When testing WhatIf functionality' {
229+
It 'Should not execute query when using WhatIf parameter' {
230+
# Get initial count
231+
$initialResult = Invoke-SqlDscQuery -ServerObject $script:serverObject -DatabaseName $script:testDatabaseName -Query 'SELECT COUNT(*) as RecordCount FROM TestTable' -PassThru -Force -ErrorAction 'Stop'
232+
$initialCount = $initialResult.Tables[0].Rows[0]['RecordCount']
233+
234+
# Run WhatIf query that would add a record
235+
$null = Invoke-SqlDscQuery -ServerObject $script:serverObject -DatabaseName $script:testDatabaseName -Query "INSERT INTO TestTable (Name, Value) VALUES ('WhatIfTest', 999)" -WhatIf -ErrorAction 'Stop'
236+
237+
# Verify count is unchanged
238+
$finalResult = Invoke-SqlDscQuery -ServerObject $script:serverObject -DatabaseName $script:testDatabaseName -Query 'SELECT COUNT(*) as RecordCount FROM TestTable' -PassThru -Force -ErrorAction 'Stop'
239+
$finalCount = $finalResult.Tables[0].Rows[0]['RecordCount']
240+
241+
$finalCount | Should -Be $initialCount
242+
}
243+
}
244+
}

tests/Integration/Commands/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ Get-SqlDscDatabase | 2 | 1 (Install-SqlDscServer), 0 (Prerequisites) | DSCSQLTES
7878
New-SqlDscDatabase | 2 | 1 (Install-SqlDscServer), 0 (Prerequisites) | DSCSQLTEST | Test databases
7979
Set-SqlDscDatabase | 2 | 1 (Install-SqlDscServer), 0 (Prerequisites) | DSCSQLTEST | -
8080
Test-SqlDscDatabase | 2 | 1 (Install-SqlDscServer), 0 (Prerequisites) | DSCSQLTEST | -
81+
Invoke-SqlDscQuery | 2 | 1 (Install-SqlDscServer), 0 (Prerequisites) | DSCSQLTEST | Test database and table
8182
ConvertTo-SqlDscDatabasePermission | 2 | 1 (Install-SqlDscServer), 0 (Prerequisites) | DSCSQLTEST | -
8283
Set-SqlDscDatabasePermission | 2 | 1 (Install-SqlDscServer), 0 (Prerequisites) | DSCSQLTEST | -
8384
Get-SqlDscAgentAlert | 2 | 1 (Install-SqlDscServer), 0 (Prerequisites) | DSCSQLTEST | -

0 commit comments

Comments
 (0)