Skip to content

Commit 9e9efc3

Browse files
authored
chore: Added integration testing of trigger handling on MS SQL (#83)
1 parent 25e950f commit 9e9efc3

File tree

11 files changed

+271
-37
lines changed

11 files changed

+271
-37
lines changed

tests/Dapper.DDD.Repository.Sql.IntegrationTests/Configuration/ContainerFixture.cs

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Reflection;
2+
using Dapper.DDD.Repository.Sql.IntegrationTests.Repositories;
23
using DotNet.Testcontainers.Builders;
34
using Microsoft.SqlServer.Management.Common;
45
using Microsoft.SqlServer.Management.Smo;
@@ -9,11 +10,11 @@ namespace Dapper.DDD.Repository.Sql.IntegrationTests.Configuration;
910
public class ContainerFixture : IAsyncLifetime, IContainerFixture
1011
{
1112
private MsSqlContainer? _container;
12-
13+
1314
public async Task InitializeAsync()
1415
{
1516
var connectionFactory = await InitializeTestContainerAsync();
16-
17+
1718
var services = new ServiceCollection();
1819
services.AddOptions();
1920
services.ConfigureDapperRepositoryDefaults(options =>
@@ -45,15 +46,15 @@ public async Task InitializeAsync()
4546
options.HasKey(x => x.Id);
4647
options.HasDefault(x => x.DateCreated);
4748
});
48-
49+
4950
services.AddViewRepository<ProductListView, int, IProductListViewRepository, ProductListViewRepository>(
5051
options =>
5152
{
5253
options.ViewName = "[Current Product List]";
5354
options.HasKey(x => x.ProductID);
5455
});
5556
services.AddViewRepository<ProductListView>(options => { options.ViewName = "[Current Product List]"; });
56-
57+
5758
services.AddTableRepository<Customer, Guid, ICustomerRepository, CustomerRepository>(options =>
5859
{
5960
options.TableName = "CustomersWithValueObject";
@@ -70,53 +71,68 @@ public async Task InitializeAsync()
7071
options.TableName = "CustomersWithNestedValueObject";
7172
options.HasKey(x => x.Id);
7273
});
74+
services.AddTableRepository<TriggerEntityWithIdentity, int, ITriggerRepositoryWithIdentity, TriggerRepositoryWithIdentity>(options =>
75+
{
76+
options.TableName = "TriggersWithIdentity";
77+
options.HasKey(e => e.Id);
78+
options.HasIdentity(e => e.Id);
79+
options.HasTriggers = true;
80+
options.HasDefault(e => e.DateCreated);
81+
});
82+
services.AddTableRepository<TriggerEntityWithoutIdentity, int, ITriggerRepositoryWithoutIdentity, TriggerRepositoryWithoutIdentity>(options =>
83+
{
84+
options.TableName = "TriggersWithoutIdentity";
85+
options.HasKey(e => e.Id);
86+
options.HasTriggers = true;
87+
options.HasDefault(e => e.DateCreated);
88+
});
7389
services.AddViewRepository<string, IInvalidQueryRepository, InvalidQueryRepository>(options => { options.ViewName = "InvalidView"; });
7490
services.AddViewRepository<DummyAggregate, int>(options => { options.ViewName = "DummyView"; });
7591
Provider = services.BuildServiceProvider();
7692
}
77-
93+
7894
public async Task DisposeAsync()
7995
{
8096
if (_container is not null)
8197
{
8298
await _container.DisposeAsync();
8399
}
84100
}
85-
101+
86102
public ServiceProvider Provider { get; private set; } = default!;
87-
103+
88104
private async Task<SqlConnectionFactory> InitializeTestContainerAsync()
89105
{
90106
_container = new MsSqlBuilder()
91107
.WithImage("mcr.microsoft.com/mssql/server:2022-latest")
92108
.WithWaitStrategy(Wait.ForUnixContainer().UntilPortIsAvailable(MsSqlBuilder.MsSqlPort))
93109
.Build();
94-
110+
95111
var startTask = _container.StartAsync();
96-
112+
97113
var northwindScript = await GetNorthwindScriptAsync();
98114
await startTask;
99115
var connectionString = _container.GetConnectionString();
100-
116+
101117
await using var sqlConnection = new SqlConnection(connectionString);
102118
var svrConnection = new ServerConnection(sqlConnection);
103119
var server = new Server(svrConnection);
104120
server.ConnectionContext.ExecuteNonQuery(northwindScript);
105-
121+
106122
return new SqlConnectionFactory(connectionString);
107123
}
108-
124+
109125
private static async Task<string> GetNorthwindScriptAsync()
110126
{
111127
var assembly = Assembly.GetExecutingAssembly();
112128
var resourceName = @"Dapper.DDD.Repository.Sql.IntegrationTests.Resources.northwind.sql";
113-
129+
114130
await using var stream = assembly.GetManifestResourceStream(resourceName);
115131
if (stream is null)
116132
{
117133
throw new InvalidOperationException("Couldn't open northwind.sql");
118134
}
119-
135+
120136
using var reader = new StreamReader(stream);
121137
return await reader.ReadToEndAsync();
122138
}

tests/Dapper.DDD.Repository.Sql.IntegrationTests/GlobalUsings.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
global using Dapper.DDD.Repository.IntegrationTests.Aggregates;
66
global using Dapper.DDD.Repository.IntegrationTests.Configuration;
77
global using Dapper.DDD.Repository.IntegrationTests.Repositories;
8+
global using Dapper.DDD.Repository.Interfaces;
9+
global using Dapper.DDD.Repository.Repositories;
810
global using Dapper.DDD.Repository.Sql.IntegrationTests.Configuration;
11+
global using Dapper.DDD.Repository.Sql.IntegrationTests.Models;
912
global using Microsoft.Data.SqlClient;
1013
global using Microsoft.Extensions.DependencyInjection;
1114
global using NetTopologySuite.Geometries;
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace Dapper.DDD.Repository.Sql.IntegrationTests.Models;
2+
3+
public record TriggerEntityWithIdentity
4+
{
5+
public int Id { get; init; }
6+
public required string Name { get; init; }
7+
public DateTime DateCreated { get; init; }
8+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace Dapper.DDD.Repository.Sql.IntegrationTests.Models;
2+
3+
public record TriggerEntityWithoutIdentity
4+
{
5+
public int Id { get; init; }
6+
public required string Name { get; init; }
7+
public DateTime DateCreated { get; init; }
8+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using Dapper.DDD.Repository.Configuration;
2+
using Microsoft.Extensions.Options;
3+
4+
namespace Dapper.DDD.Repository.Sql.IntegrationTests.Repositories;
5+
6+
public interface ITriggerRepositoryWithoutIdentity : ITableRepository<TriggerEntityWithoutIdentity, int>
7+
{
8+
}
9+
10+
public class TriggerRepositoryWithoutIdentity : TableRepository<TriggerEntityWithoutIdentity, int>, ITriggerRepositoryWithoutIdentity
11+
{
12+
public TriggerRepositoryWithoutIdentity(IOptions<TableAggregateConfiguration<TriggerEntityWithoutIdentity>> options, IOptions<DefaultConfiguration>? defaultOptions) : base(options, defaultOptions)
13+
{
14+
}
15+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using Dapper.DDD.Repository.Configuration;
2+
using Microsoft.Extensions.Options;
3+
4+
namespace Dapper.DDD.Repository.Sql.IntegrationTests.Repositories;
5+
6+
public interface ITriggerRepositoryWithIdentity : ITableRepository<TriggerEntityWithIdentity, int>
7+
{
8+
}
9+
10+
public class TriggerRepositoryWithIdentity : TableRepository<TriggerEntityWithIdentity, int>, ITriggerRepositoryWithIdentity
11+
{
12+
public TriggerRepositoryWithIdentity(IOptions<TableAggregateConfiguration<TriggerEntityWithIdentity>> options, IOptions<DefaultConfiguration>? defaultOptions) : base(options, defaultOptions)
13+
{
14+
}
15+
}

tests/Dapper.DDD.Repository.Sql.IntegrationTests/Resources/northwind.sql

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12395,4 +12395,33 @@ CREATE TABLE CustomersWithNestedValueObject
1239512395
GO
1239612396
ALTER TABLE CustomersWithNestedValueObject
1239712397
ADD CONSTRAINT PK_CustomersWithNestedValueObject PRIMARY KEY (Id);
12398-
GO
12398+
GO
12399+
CREATE TABLE TriggersWithIdentity
12400+
(
12401+
Id INT NOT NULL PRIMARY KEY IDENTITY(1,1),
12402+
Name VARCHAR(100) NOT NULL,
12403+
DateCreated DATETIME NOT NULL DEFAULT(GETUTCDATE())
12404+
);
12405+
GO
12406+
CREATE TRIGGER trigger_with_identity
12407+
ON TriggersWithIdentity
12408+
AFTER INSERT
12409+
AS
12410+
PRINT 'TRIGGER!!!'
12411+
12412+
GO
12413+
12414+
CREATE TABLE TriggersWithoutIdentity
12415+
(
12416+
Id INT NOT NULL PRIMARY KEY,
12417+
Name VARCHAR(100) NOT NULL,
12418+
DateCreated DATETIME NOT NULL DEFAULT(GETUTCDATE())
12419+
);
12420+
GO
12421+
CREATE TRIGGER trigger_without_identity
12422+
ON TriggersWithoutIdentity
12423+
AFTER INSERT
12424+
AS
12425+
PRINT 'TRIGGER!!!'
12426+
12427+
GO

tests/Dapper.DDD.Repository.Sql.IntegrationTests/SerializedColumnTests.cs

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
1-
using Dapper.DDD.Repository.Interfaces;
2-
3-
namespace Dapper.DDD.Repository.Sql.IntegrationTests;
1+
namespace Dapper.DDD.Repository.Sql.IntegrationTests;
42

53
[Collection(Consts.DatabaseCollection)]
64
public class SerializedColumnTests
75
{
86
private readonly ITableRepository<City, Guid> _repository;
9-
7+
108
public SerializedColumnTests(ContainerFixture containerFixture)
119
{
1210
_repository = containerFixture.Provider.GetRequiredService<ITableRepository<City, Guid>>();
1311
}
14-
12+
1513
[Fact]
1614
public async Task Delete_Valid_GeometryIsIncludedInReturnValue()
1715
{
@@ -27,16 +25,16 @@ public async Task Delete_Valid_GeometryIsIncludedInReturnValue()
2725
};
2826
city.GeoLocation.SRID = 25832;
2927
city.Area.SRID = 25832;
30-
28+
3129
await _repository.InsertAsync(city);
32-
30+
3331
// Act
3432
var result = await _repository.DeleteAsync(city.Id);
35-
33+
3634
// Assert
3735
Assert.Equal(city, result);
3836
}
39-
37+
4038
[Fact]
4139
public async Task Insert_Valid_GeometryIsIncludedInReturnValue()
4240
{
@@ -52,10 +50,10 @@ public async Task Insert_Valid_GeometryIsIncludedInReturnValue()
5250
};
5351
city.GeoLocation.SRID = 25832;
5452
city.Area.SRID = 25832;
55-
53+
5654
// Act
5755
var result = await _repository.InsertAsync(city);
58-
56+
5957
// Assert
6058
try
6159
{
@@ -68,7 +66,7 @@ public async Task Insert_Valid_GeometryIsIncludedInReturnValue()
6866
await _repository.DeleteAsync(city.Id);
6967
}
7068
}
71-
69+
7270
[Fact]
7371
public async Task GetAll_Valid_GeometryIsIncludedInReturnValue()
7472
{
@@ -85,10 +83,10 @@ public async Task GetAll_Valid_GeometryIsIncludedInReturnValue()
8583
city.GeoLocation.SRID = 25832;
8684
city.Area.SRID = 25832;
8785
await _repository.InsertAsync(city);
88-
86+
8987
// Act
9088
var result = (await _repository.GetAllAsync()).ToList();
91-
89+
9290
// Assert
9391
try
9492
{
@@ -101,7 +99,7 @@ public async Task GetAll_Valid_GeometryIsIncludedInReturnValue()
10199
await _repository.DeleteAsync(city.Id);
102100
}
103101
}
104-
102+
105103
[Fact]
106104
public async Task Get_Valid_GeometryIsIncludedInReturnValue()
107105
{
@@ -118,10 +116,10 @@ public async Task Get_Valid_GeometryIsIncludedInReturnValue()
118116
city.GeoLocation.SRID = 25832;
119117
city.Area.SRID = 25832;
120118
await _repository.InsertAsync(city);
121-
119+
122120
// Act
123121
var fetchedCity = await _repository.GetAsync(city.Id);
124-
122+
125123
// Assert
126124
try
127125
{
@@ -132,7 +130,7 @@ public async Task Get_Valid_GeometryIsIncludedInReturnValue()
132130
await _repository.DeleteAsync(city.Id);
133131
}
134132
}
135-
133+
136134
[Fact]
137135
public async Task Update_Valid_GeometryIsIncludedInReturnValue()
138136
{
@@ -149,15 +147,15 @@ public async Task Update_Valid_GeometryIsIncludedInReturnValue()
149147
city.GeoLocation.SRID = 25832;
150148
city.Area.SRID = 25832;
151149
await _repository.InsertAsync(city);
152-
150+
153151
// Act
154152
var newArea = Geometry.DefaultFactory.CreatePolygon(new Coordinate[]
155153
{
156154
new(10, 10), new(10, 20), new(20, 20), new(20, 10), new(10, 10)
157155
});
158156
newArea.SRID = 1234;
159157
var updatedCity = await _repository.UpdateAsync(city with { Area = newArea });
160-
158+
161159
// Assert
162160
try
163161
{

tests/Dapper.DDD.Repository.Sql.IntegrationTests/SinglePrimaryKeyAsyncTests.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
namespace Dapper.DDD.Repository.Sql.IntegrationTests;
44

55
public class SinglePrimaryKeyAsyncTests : BaseSinglePrimaryKeyAsyncTests<DapperRepositoryQueryException>
6-
76
{
87
public SinglePrimaryKeyAsyncTests(ContainerFixture containerFixture) : base(containerFixture)
98
{

tests/Dapper.DDD.Repository.Sql.IntegrationTests/SqlConnectionFactory.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System.Data;
2-
using Dapper.DDD.Repository.Interfaces;
32

43
namespace Dapper.DDD.Repository.Sql.IntegrationTests;
54

0 commit comments

Comments
 (0)