1
+ using Microsoft . Data . Sqlite ;
2
+ using Microsoft . Extensions . Logging . Abstractions ;
3
+ using Cosmos . DataTransfer . Interfaces ;
4
+ using Cosmos . DataTransfer . Common ;
5
+ using Cosmos . DataTransfer . Common . UnitTests ;
6
+
7
+ namespace Cosmos . DataTransfer . SqlServerExtension . UnitTests ;
8
+
9
+ [ TestClass ]
10
+ public class SqlServerDataSourceExtensionTests
11
+ {
12
+
13
+ private static async Task < Func < string , ValueTask < System . Data . Common . DbConnection > > > connectionFactory ( CancellationToken cancellationToken = default ( CancellationToken ) ) {
14
+ var connection = new SqliteConnection ( "" ) ;
15
+ await connection . OpenAsync ( cancellationToken ) ;
16
+
17
+ var cmd = connection . CreateCommand ( ) ;
18
+ cmd . CommandText = @"CREATE TABLE foobar (
19
+ id INTEGER NOT NULL,
20
+ name TEXT
21
+ );" ;
22
+ await cmd . ExecuteNonQueryAsync ( cancellationToken ) ;
23
+ cmd . CommandText = @"INSERT INTO foobar (id, name)
24
+ VALUES (1, 'zoo');" ;
25
+ await cmd . ExecuteNonQueryAsync ( cancellationToken ) ;
26
+ cmd . CommandText = @"INSERT INTO foobar (id, name)
27
+ VALUES (2, NULL);" ;
28
+ await cmd . ExecuteNonQueryAsync ( cancellationToken ) ;
29
+
30
+ var func = ( string connectionString ) => {
31
+ return new ValueTask < System . Data . Common . DbConnection > ( connection ) ;
32
+ } ;
33
+
34
+ return func ;
35
+ }
36
+
37
+ [ TestMethod ]
38
+ public async Task TestReadAsync_QueryText ( ) {
39
+ var extension = new SqlServerDataSourceExtension ( ) ;
40
+ var config = TestHelpers . CreateConfig ( new Dictionary < string , string > {
41
+ { "ConnectionString" , "Sqlite" } ,
42
+ { "QueryText" , "SELECT * FROM foobar" }
43
+ } ) ;
44
+ Assert . AreEqual ( "SqlServer" , extension . DisplayName ) ;
45
+
46
+ var cancellationToken = new CancellationTokenSource ( 500 ) ;
47
+
48
+ var result = await extension . ReadAsync ( config , NullLogger . Instance , await connectionFactory ( cancellationToken . Token ) , cancellationToken . Token ) . ToListAsync ( ) ;
49
+ var expected = new List < DictionaryDataItem > {
50
+ new DictionaryDataItem ( new Dictionary < string , object ? > { { "id" , ( long ) 1 } , { "name" , "zoo" } } ) ,
51
+ new DictionaryDataItem ( new Dictionary < string , object ? > { { "id" , ( long ) 2 } , { "name" , null } } )
52
+ } ;
53
+ CollectionAssert . That . AreEqual ( expected , result , new DataItemComparer ( ) ) ;
54
+ }
55
+
56
+ [ TestMethod ]
57
+ public async Task TestReadAsync_FromFile ( ) {
58
+ var outputFile = Path . GetTempFileName ( ) ;
59
+ await File . WriteAllTextAsync ( outputFile , "SELECT * FROM foobar;" ) ;
60
+ var extension = new SqlServerDataSourceExtension ( ) ;
61
+ var config = TestHelpers . CreateConfig ( new Dictionary < string , string > {
62
+ { "ConnectionString" , "Sqlite" } ,
63
+ { "FilePath" , outputFile }
64
+ } ) ;
65
+
66
+
67
+ var cancellationToken = new CancellationTokenSource ( 500 ) ;
68
+
69
+ var result = await extension . ReadAsync ( config , NullLogger . Instance , await connectionFactory ( cancellationToken . Token ) , cancellationToken . Token ) . ToListAsync ( ) ;
70
+ var expected = new List < DictionaryDataItem > {
71
+ new DictionaryDataItem ( new Dictionary < string , object ? > { { "id" , ( long ) 1 } , { "name" , "zoo" } } ) ,
72
+ new DictionaryDataItem ( new Dictionary < string , object ? > { { "id" , ( long ) 2 } , { "name" , null } } )
73
+ } ;
74
+ CollectionAssert . That . AreEqual ( expected , result , new DataItemComparer ( ) ) ;
75
+ }
76
+
77
+ // Allows for testing against an actual SQL Server by specifying a
78
+ // connectionstring in either a .runsettings-file or environment variable.
79
+ // Example: Using sql.runsettings
80
+ // <?xml version="1.0" encoding="utf-8"?>
81
+ // <RunSettings>
82
+ // <TestRunParameters>
83
+ // <Parameter name="TestReadAsync_LiveSqlServer_ConnectionString" value="<Your connection string>" />
84
+ // </TestRunParameters>
85
+ // </RunSettings>
86
+ // run test with dotnet test --settings sql.runsettings
87
+ #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
88
+ public TestContext TestContext { get ; set ; }
89
+ #pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
90
+ [ TestMethod ]
91
+ [ Timeout ( 1000 ) ]
92
+ public async Task TestReadAsync_LiveSqlServer ( ) {
93
+ var connectionString = ( string ? ) TestContext . Properties [ "TestReadAsync_LiveSqlServer_ConnectionString" ] ;
94
+ connectionString ??= Environment . GetEnvironmentVariable ( "TestReadAsync_LiveSqlServer_ConnectionString" ) ;
95
+ if ( connectionString is null ) {
96
+ Assert . Inconclusive ( "Could not run, as no connection string to live SQL Server was provided." ) ;
97
+ }
98
+
99
+ var extension = new SqlServerDataSourceExtension ( ) ;
100
+ var config = TestHelpers . CreateConfig ( new Dictionary < string , string > {
101
+ { "ConnectionString" , connectionString ! } ,
102
+ { "QueryText" , "SELECT 1, 'foo' as bar, NULL as zoo;" }
103
+ } ) ;
104
+
105
+ var result = await extension . ReadAsync ( config , NullLogger . Instance ) . FirstAsync ( ) ;
106
+
107
+ Assert . IsTrue ( new DataItemComparer ( ) . Equals ( result ,
108
+ new DictionaryDataItem ( new Dictionary < string , object ? > {
109
+ { "" , 1 } ,
110
+ { "bar" , "foo" } ,
111
+ { "zoo" , null }
112
+ } ) ) ) ;
113
+ }
114
+ }
0 commit comments