Skip to content

Commit 66f4357

Browse files
committed
Add tests for the CommandBuilder class
1 parent 7627c61 commit 66f4357

File tree

5 files changed

+141
-34
lines changed

5 files changed

+141
-34
lines changed

src/Sql/Command.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ namespace Belin.Sql;
55
/// </summary>
66
/// <param name="Text">The text of the SQL statement.</param>
77
/// <param name="Parameters">The parameters of the SQL statement.</param>
8-
public sealed record Command(string Text, ParameterCollection? Parameters = null);
8+
public sealed record Command(string Text, ParameterCollection Parameters);

src/Sql/CommandBuilder.cs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,8 @@ public CommandBuilder(IDbConnection connection) {
9797
public Command GetDeleteCommand<T>(T instance) where T: new() {
9898
var table = Mapper.Instance.GetTable<T>();
9999
var identityColumn = table.IdentityColumn ?? throw new InvalidOperationException("The identity column could not be found.");
100-
var parameter = new Parameter(UsePositionalParameters ? "?1" : GetParameterName(identityColumn.Name), identityColumn.GetValue(instance));
101100

101+
var parameter = new Parameter(UsePositionalParameters ? "?1" : GetParameterName(identityColumn.Name), identityColumn.GetValue(instance));
102102
var text = $"""
103103
DELETE FROM {GetTableName(table)}
104104
WHERE {QuoteIdentifier(identityColumn.Name)} = {(UsePositionalParameters ? "?" : parameter.Name)}
@@ -117,8 +117,8 @@ public CommandBuilder(IDbConnection connection) {
117117
public Command GetExistsCommand<T>(object id) where T: new() {
118118
var table = Mapper.Instance.GetTable<T>();
119119
var identityColumn = table.IdentityColumn ?? throw new InvalidOperationException("The identity column could not be found.");
120-
var parameter = new Parameter(UsePositionalParameters ? "?1" : GetParameterName(identityColumn.Name), id);
121120

121+
var parameter = new Parameter(UsePositionalParameters ? "?1" : GetParameterName(identityColumn.Name), id);
122122
var text = $"""
123123
SELECT 1
124124
FROM {GetTableName(table)}
@@ -139,10 +139,14 @@ SELECT 1
139139
public Command GetFindCommand<T>(object id, params string[] columns) where T: new() {
140140
var table = Mapper.Instance.GetTable<T>();
141141
var identityColumn = table.IdentityColumn ?? throw new InvalidOperationException("The identity column could not be found.");
142-
var parameter = new Parameter(UsePositionalParameters ? "?1" : GetParameterName(identityColumn.Name), id);
143142

143+
var fields = (columns.Length == 0 ? table.Columns.Values : table.Columns.Values.Where(column => columns.Contains(column.Name)))
144+
.Where(column => column.CanWrite)
145+
.Select(column => column.Name);
146+
147+
var parameter = new Parameter(UsePositionalParameters ? "?1" : GetParameterName(identityColumn.Name), id);
144148
var text = $"""
145-
SELECT {(columns.Length == 0 ? "*" : string.Join(", ", columns.Select(QuoteIdentifier)))}
149+
SELECT {string.Join(", ", fields.Select(QuoteIdentifier))}
146150
FROM {GetTableName(table)}
147151
WHERE {QuoteIdentifier(identityColumn.Name)} = {(UsePositionalParameters ? "?" : parameter.Name)}
148152
""";
@@ -160,8 +164,8 @@ SELECT 1
160164
public Command GetInsertCommand<T>(T instance) where T: new() {
161165
var table = Mapper.Instance.GetTable<T>();
162166
var identityColumn = table.IdentityColumn ?? throw new InvalidOperationException("The identity column could not be found.");
163-
var fields = table.Columns.Values.Where(column => column.CanRead && !column.IsComputed).ToArray();
164167

168+
var fields = table.Columns.Values.Where(column => column.CanRead && !column.IsComputed).ToArray();
165169
var text = $"""
166170
INSERT INTO {GetTableName(table)} ({string.Join(", ", fields.Select(field => QuoteIdentifier(field.Name)))})
167171
VALUES ({string.Join(", ", fields.Select(field => UsePositionalParameters ? "?" : GetParameterName(field.Name)))})
@@ -184,6 +188,7 @@ .. fields.Select((field, index) => (UsePositionalParameters ? $"?{index}" : GetP
184188
public Command GetUpdateCommand<T>(T instance, params string[] columns) where T: new() {
185189
var table = Mapper.Instance.GetTable<T>();
186190
var identityColumn = table.IdentityColumn ?? throw new InvalidOperationException("The identity column could not be found.");
191+
187192
var fields = (columns.Length == 0 ? table.Columns.Values : table.Columns.Values.Where(column => columns.Contains(column.Name)))
188193
.Where(column => column.CanRead && !column.IsComputed)
189194
.ToArray();

test/Cmdlets/Get-Mapper.Tests.ps1

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,18 @@ Describe "Get-Mapper" {
1010
Describe "CreateInstance()" {
1111
It "should create instances of the requested type" {
1212
$properties = @{
13-
Class = "Bard/minstrel"
14-
FirstName = "Cédric"
15-
Gender = [CharacterGender]::Balrog.ToString()
16-
LastName = $null
13+
CLASS = "Bard/minstrel"
14+
firstName = "Cédric"
15+
gender = [CharacterGender]::Balrog.ToString()
16+
lastName = $null
1717
}
1818

1919
$instance = (Get-SqlMapper).CreateInstance($properties)
2020
$instance.GetType().FullName | Should -BeExactly System.Dynamic.ExpandoObject
21-
$instance.Class | Should -BeExactly "Bard/minstrel"
22-
$instance.FirstName | Should -BeExactly "Cédric"
23-
$instance.Gender | Should -BeExactly ([CharacterGender]::Balrog.ToString())
24-
$instance.LastName | Should -Be $null
21+
$instance.CLASS | Should -BeExactly "Bard/minstrel"
22+
$instance.firstName | Should -BeExactly "Cédric"
23+
$instance.gender | Should -BeExactly ([CharacterGender]::Balrog.ToString())
24+
$instance.lastName | Should -Be $null
2525

2626
$character = (Get-SqlMapper).CreateInstance[Character]($properties)
2727
$character.GetType().Name | Should -BeExactly Character
@@ -39,13 +39,13 @@ Describe "Get-Mapper" {
3939
$table.Type | Should -Be ([Character])
4040

4141
$table.Columns.Keys | Should -HaveCount 5
42-
$table.IdentityColumn | Should -Be $table.Columns["Id"]
43-
$table.Columns["Gender"].Type | Should -Be ([CharacterGender])
44-
$table.Columns["LastName"].Type | Should -Be ([string])
42+
$table.IdentityColumn | Should -Be $table.Columns["ID"]
43+
$table.Columns["gender"].Type | Should -Be ([CharacterGender])
44+
$table.Columns["lastName"].Type | Should -Be ([string])
4545

46-
$table.Columns["FirstName"].CanWrite | Should -BeTrue
47-
$table.Columns["FullName"].IsComputed | Should -BeTrue
48-
$table.Columns["Id"].IsIdentity | Should -BeTrue
46+
$table.Columns["firstName"].CanWrite | Should -BeTrue
47+
$table.Columns["fullName"].IsComputed | Should -BeTrue
48+
$table.Columns["ID"].IsIdentity | Should -BeTrue
4949
}
5050
}
5151
}

test/CommandBuilder.Tests.cs

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
namespace Belin.Sql;
2+
3+
using Belin.Sql.Fixtures;
4+
using System.Data.SQLite;
5+
6+
/// <summary>
7+
/// Tests the features of the <see cref="CommandBuilder"/> class.
8+
/// </summary>
9+
[TestClass]
10+
public sealed class CommandBuilderTests {
11+
12+
/// <summary>
13+
/// The connection to the data source.
14+
/// </summary>
15+
private SQLiteConnection connection = default!;
16+
17+
/// <summary>
18+
/// The test data.
19+
/// </summary>
20+
private readonly Character record = new() { Id = 1000, FirstName = "Cédric", Gender = CharacterGender.DarkLord };
21+
22+
[TestInitialize]
23+
public void TestInitialize() => connection = That.CreateInMemoryDatabase();
24+
25+
[TestCleanup]
26+
public void TestCleanup() => connection.Close();
27+
28+
[TestMethod]
29+
public void GetDeleteCommand() {
30+
var command = new CommandBuilder(connection).GetDeleteCommand(record);
31+
StartsWith(@"DELETE FROM ""main"".""Characters""", command.Text);
32+
EndsWith(@"WHERE ""ID"" = @ID", command.Text);
33+
34+
var parameter = command.Parameters.Single();
35+
AreEqual("@ID", parameter.Name);
36+
AreEqual(1000, parameter.Value);
37+
}
38+
39+
[TestMethod]
40+
public void GetExistsCommand() {
41+
var command = new CommandBuilder(connection).GetExistsCommand<Character>(record.Id);
42+
StartsWith("SELECT 1", command.Text);
43+
Contains(@"FROM ""main"".""Characters""", command.Text);
44+
EndsWith(@"WHERE ""ID"" = @ID", command.Text);
45+
46+
var parameter = command.Parameters.Single();
47+
AreEqual("@ID", parameter.Name);
48+
AreEqual(1000, parameter.Value);
49+
}
50+
51+
[TestMethod]
52+
public void GetFindCommand() {
53+
var builder = new CommandBuilder(connection);
54+
55+
var command = builder.GetFindCommand<Character>(record.Id);
56+
StartsWith(@"SELECT """, command.Text);
57+
DoesNotContain("*", command.Text);
58+
Contains(@"FROM ""main"".""Characters""", command.Text);
59+
EndsWith(@"WHERE ""ID"" = @ID", command.Text);
60+
61+
var parameter = command.Parameters.Single();
62+
AreEqual("@ID", parameter.Name);
63+
AreEqual(1000, parameter.Value);
64+
65+
command = builder.GetFindCommand<Character>(record.Id, ["firstName"]);
66+
StartsWith(@"SELECT ""firstName""", command.Text);
67+
DoesNotContain("gender", command.Text);
68+
DoesNotContain("lastName", command.Text);
69+
}
70+
71+
[TestMethod]
72+
public void GetInsertCommand() {
73+
var command = new CommandBuilder(connection).GetInsertCommand(record);
74+
StartsWith(@"INSERT INTO ""main"".""Characters"" (", command.Text);
75+
Contains("VALUES (", command.Text);
76+
77+
var parameters = command.Parameters;
78+
HasCount(3, parameters);
79+
AreEqual("Cédric", parameters["firstName"].Value);
80+
AreEqual(CharacterGender.DarkLord, parameters["gender"].Value);
81+
AreEqual("", parameters["lastName"].Value);
82+
}
83+
84+
[TestMethod]
85+
public void GetUpdateCommand() {
86+
var builder = new CommandBuilder(connection);
87+
88+
var command = builder.GetUpdateCommand(record);
89+
StartsWith(@"UPDATE ""main"".""Characters""", command.Text);
90+
Contains(@"SET """, command.Text);
91+
EndsWith(@"WHERE ""ID"" = @ID", command.Text);
92+
93+
var parameters = command.Parameters;
94+
HasCount(4, parameters);
95+
AreEqual("Cédric", parameters["firstName"].Value);
96+
AreEqual(CharacterGender.DarkLord, parameters["gender"].Value);
97+
AreEqual(1000, parameters["ID"].Value);
98+
AreEqual("", parameters["lastName"].Value);
99+
100+
HasCount(2, builder.GetUpdateCommand(record, "lastName").Parameters);
101+
}
102+
}

test/Mapper.Tests.cs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -74,17 +74,17 @@ public void ChangeType(object? value, Type conversionType, bool isNullable, obje
7474
[TestMethod]
7575
public void CreateInstance() {
7676
var properties = new Dictionary<string, object?> {
77-
["Class"] = "Bard/minstrel",
78-
["FirstName"] = "Cédric",
79-
["Gender"] = CharacterGender.Balrog.ToString(),
80-
["LastName"] = null
77+
["CLASS"] = "Bard/minstrel",
78+
["firstName"] = "Cédric",
79+
["gender"] = CharacterGender.Balrog.ToString(),
80+
["lastName"] = null
8181
};
8282

8383
dynamic instance = Mapper.Instance.CreateInstance(properties);
84-
AreEqual("Bard/minstrel", instance.Class);
85-
AreEqual("Cédric", instance.FirstName);
86-
AreEqual(CharacterGender.Balrog.ToString(), instance.Gender);
87-
IsNull(instance.LastName);
84+
AreEqual("Bard/minstrel", instance.CLASS);
85+
AreEqual("Cédric", instance.firstName);
86+
AreEqual(CharacterGender.Balrog.ToString(), instance.gender);
87+
IsNull(instance.lastName);
8888

8989
var character = Mapper.Instance.CreateInstance<Character>(properties);
9090
AreEqual("Cédric", character.FirstName);
@@ -100,13 +100,13 @@ public void GetTable() {
100100
AreEqual(typeof(Character), table.Type);
101101

102102
HasCount(5, table.Columns.Keys);
103-
AreEqual(table.Columns[nameof(Character.Id)], table.IdentityColumn);
104-
AreEqual(typeof(CharacterGender), table.Columns[nameof(Character.Gender)].Type);
105-
AreEqual(typeof(string), table.Columns[nameof(Character.LastName)].Type);
103+
AreEqual(table.Columns["ID"], table.IdentityColumn);
104+
AreEqual(typeof(CharacterGender), table.Columns["gender"].Type);
105+
AreEqual(typeof(string), table.Columns["lastName"].Type);
106106

107-
IsTrue(table.Columns[nameof(Character.FirstName)].CanWrite);
108-
IsTrue(table.Columns[nameof(Character.FullName)].IsComputed);
109-
IsTrue(table.Columns[nameof(Character.Id)].IsIdentity);
107+
IsTrue(table.Columns["firstName"].CanWrite);
108+
IsTrue(table.Columns["fullName"].IsComputed);
109+
IsTrue(table.Columns["ID"].IsIdentity);
110110
}
111111

112112
[TestMethod]

0 commit comments

Comments
 (0)