Skip to content

Commit 440824f

Browse files
committed
Add unit tests for EntityFrameworkCore extensions
Introduced comprehensive unit tests to validate `UnitOfWork`, `ReadonlyUnitOfWork`, and associated factory behaviors in the `CodeOfChaos.Extensions.EntityFrameworkCore` library.
1 parent 38d7afd commit 440824f

28 files changed

+1649
-193
lines changed

Directory.Packages.props

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@
77
<ItemGroup Condition="'$(TargetFramework)' == 'net10.0'">
88
<PackageVersion Include="Microsoft.AspNetCore.Components" Version="10.0.0" />
99
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="10.0.0" />
10+
<PackageVersion Include="Microsoft.EntityFrameworkCore.InMemory" Version="10.0.0" />
1011
</ItemGroup>
1112
<!-- .NET 9 -->
1213
<ItemGroup Condition="'$(TargetFramework)' == 'net9.0'">
1314
<PackageVersion Include="Microsoft.AspNetCore.Components" Version="[9.0.11, 10.0.0)" />
1415
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="[9.0.11, 10.0.0)" />
16+
<PackageVersion Include="Microsoft.EntityFrameworkCore.InMemory" Version="[9.0.11, 10.0.0)" />
1517
</ItemGroup>
1618
<!-- Common packages for all frameworks -->
1719
<ItemGroup>

src/CodeOfChaos.Extensions.EntityFrameworkCore/CodeOfChaos.Extensions.EntityFrameworkCore.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@
2626
<PackageReference Include="Microsoft.EntityFrameworkCore" />
2727
</ItemGroup>
2828

29+
<ItemGroup>
30+
<InternalsVisibleTo Include="Tests.CodeOfChaos.Extensions.EntityFrameworkCore" />
31+
</ItemGroup>
32+
2933
<ItemGroup>
3034
<None Include="..\..\LICENSE" Pack="true" PackagePath="" Visible="false" />
3135
<None Include="README.md" Pack="true" PackagePath="" />
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
2+
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=contracts/@EntryIndexedValue">True</s:Boolean>
3+
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=linq/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// ---------------------------------------------------------------------------------------------------------------------
2+
// Imports
3+
// ---------------------------------------------------------------------------------------------------------------------
4+
namespace Microsoft.EntityFrameworkCore;
5+
6+
// ---------------------------------------------------------------------------------------------------------------------
7+
// Code
8+
// ---------------------------------------------------------------------------------------------------------------------
9+
public interface IReadonlyCapableDbContext {
10+
bool IsReadonly { get; }
11+
void SetAsReadonly();
12+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// ---------------------------------------------------------------------------------------------------------------------
2+
// Imports
3+
// ---------------------------------------------------------------------------------------------------------------------
4+
namespace Microsoft.EntityFrameworkCore;
5+
6+
// ---------------------------------------------------------------------------------------------------------------------
7+
// Code
8+
// ---------------------------------------------------------------------------------------------------------------------
9+
public interface IReadonlyUnitOfWork<TDbContext> : IUnitOfWork<TDbContext> where TDbContext : DbContext ;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// ---------------------------------------------------------------------------------------------------------------------
2+
// Imports
3+
// ---------------------------------------------------------------------------------------------------------------------
4+
namespace Microsoft.EntityFrameworkCore;
5+
6+
// ---------------------------------------------------------------------------------------------------------------------
7+
// Code
8+
// ---------------------------------------------------------------------------------------------------------------------
9+
public interface IReadonlyUnitOfWorkFactory<TDbContext> where TDbContext : DbContext {
10+
IReadonlyUnitOfWork<TDbContext> Create();
11+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// ---------------------------------------------------------------------------------------------------------------------
2+
// Imports
3+
// ---------------------------------------------------------------------------------------------------------------------
4+
namespace Microsoft.EntityFrameworkCore;
5+
// ---------------------------------------------------------------------------------------------------------------------
6+
// Code
7+
// ---------------------------------------------------------------------------------------------------------------------
8+
public interface IUnitOfWork<TDbContext> : IAsyncDisposable where TDbContext : DbContext {
9+
// -----------------------------------------------------------------------------------------------------------------
10+
// Methods
11+
// ----------------------------------------------------------------------------------------------------------------
12+
void SaveChanges();
13+
ValueTask SaveChangesAsync(CancellationToken ct = default);
14+
15+
bool TryCommitTransaction();
16+
ValueTask<bool> TryCommitTransactionAsync(CancellationToken ct = default);
17+
18+
bool TryCreateTransaction();
19+
ValueTask<bool> TryCreateTransactionAsync(CancellationToken ct = default);
20+
21+
bool TryRollbackTransaction();
22+
ValueTask<bool> TryRollbackTransactionAsync(CancellationToken ct = default);
23+
24+
bool TryCreateSavepoint(Guid id);
25+
ValueTask<bool> TryCreateSavepointAsync(Guid id, CancellationToken ct = default);
26+
27+
bool TryRollbackToSavepoint(Guid id);
28+
ValueTask<bool> TryRollbackToSavepointAsync(Guid id, CancellationToken ct = default);
29+
30+
TDbContext GetDbContext();
31+
ValueTask<TDbContext> GetDbContextAsync(CancellationToken ct = default);
32+
33+
TRepo GetRepository<TRepo>() where TRepo : class, IUnitOfWorkRepository;
34+
ValueTask<TRepo> GetRepositoryAsync<TRepo>(CancellationToken ct = default) where TRepo : class, IUnitOfWorkRepository;
35+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// ---------------------------------------------------------------------------------------------------------------------
2+
// Imports
3+
// ---------------------------------------------------------------------------------------------------------------------
4+
using System.Diagnostics.CodeAnalysis;
5+
6+
namespace Microsoft.EntityFrameworkCore;
7+
// ---------------------------------------------------------------------------------------------------------------------
8+
// Code
9+
// ---------------------------------------------------------------------------------------------------------------------
10+
public interface IUnitOfWorkFactory<TDbContext> where TDbContext : DbContext {
11+
IUnitOfWork<TDbContext> Create();
12+
13+
IUnitOfWork<TDbContext> CreateWithTransaction();
14+
ValueTask<IUnitOfWork<TDbContext>> CreateWithTransactionAsync(CancellationToken ct = default);
15+
16+
bool TryCreateWithTransaction([NotNullWhen(true)] out IUnitOfWork<TDbContext>? unitOfWork);
17+
ValueTask<IUnitOfWork<TDbContext>?> TryCreateWithTransactionAsync(CancellationToken ct = default);
18+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// ---------------------------------------------------------------------------------------------------------------------
2+
// Imports
3+
// ---------------------------------------------------------------------------------------------------------------------
4+
namespace Microsoft.EntityFrameworkCore;
5+
// ---------------------------------------------------------------------------------------------------------------------
6+
// Code
7+
// ---------------------------------------------------------------------------------------------------------------------
8+
public interface IUnitOfWorkRepository;
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,65 @@
1-
// ---------------------------------------------------------------------------------------------------------------------
2-
// Imports
3-
// ---------------------------------------------------------------------------------------------------------------------
4-
using System.Diagnostics;
5-
6-
namespace Microsoft.EntityFrameworkCore;
7-
// ---------------------------------------------------------------------------------------------------------------------
8-
// Code
9-
// ---------------------------------------------------------------------------------------------------------------------
10-
public static class LinqConditionalWithExtensions {
11-
12-
[DebuggerStepThrough]
13-
public static IQueryable<T> ConditionalWith<T>(this IQueryable<T> source, bool condition, Func<IQueryable<T>, IQueryable<T>> query)
14-
=> condition
15-
? query(source)
16-
: source;
17-
18-
[DebuggerStepThrough]
19-
public static IQueryable<T> ConditionalWith<T, T0>(this IQueryable<T> source, bool condition, Func<IQueryable<T>, T0, IQueryable<T>> query, T0 arg0)
20-
=> condition
21-
? query(source, arg0)
22-
: source;
23-
24-
[DebuggerStepThrough]
25-
public static IQueryable<T> ConditionalWith<T, T0, T1>(this IQueryable<T> source, bool condition, Func<IQueryable<T>, T0, T1, IQueryable<T>> query, T0 arg0, T1 arg1)
26-
=> condition
27-
? query(source, arg0, arg1)
28-
: source;
29-
30-
[DebuggerStepThrough]
31-
public static IQueryable<T> ConditionalWith<T, T0, T1, T2>(this IQueryable<T> source, bool condition, Func<IQueryable<T>, T0, T1, T2, IQueryable<T>> query, T0 arg0, T1 arg1, T2 arg2)
32-
=> condition
33-
? query(source, arg0, arg1, arg2)
34-
: source;
35-
36-
[DebuggerStepThrough]
37-
public static IQueryable<T> ConditionalWith<T, T0, T1, T2, T3>(this IQueryable<T> source, bool condition, Func<IQueryable<T>, T0, T1, T2, T3, IQueryable<T>> query, T0 arg0, T1 arg1, T2 arg2, T3 arg3)
38-
=> condition
39-
? query(source, arg0, arg1, arg2, arg3)
40-
: source;
41-
42-
[DebuggerStepThrough]
43-
public static IQueryable<T> ConditionalWith<T, T0, T1, T2, T3, T4>(this IQueryable<T> source, bool condition, Func<IQueryable<T>, T0, T1, T2, T3, T4, IQueryable<T>> query, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4)
44-
=> condition
45-
? query(source, arg0, arg1, arg2, arg3, arg4)
46-
: source;
47-
48-
[DebuggerStepThrough]
49-
public static IQueryable<T> ConditionalWith<T, T0, T1, T2, T3, T4, T5>(this IQueryable<T> source, bool condition, Func<IQueryable<T>, T0, T1, T2, T3, T4, T5, IQueryable<T>> query, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5)
50-
=> condition
51-
? query(source, arg0, arg1, arg2, arg3, arg4, arg5)
52-
: source;
53-
54-
[DebuggerStepThrough]
55-
public static IQueryable<T> ConditionalWith<T, T0, T1, T2, T3, T4, T5, T6>(this IQueryable<T> source, bool condition, Func<IQueryable<T>, T0, T1, T2, T3, T4, T5, T6, IQueryable<T>> query, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6)
56-
=> condition
57-
? query(source, arg0, arg1, arg2, arg3, arg4, arg5, arg6)
58-
: source;
59-
60-
[DebuggerStepThrough]
61-
public static IQueryable<T> ConditionalWith<T, T0, T1, T2, T3, T4, T5, T6, T7>(this IQueryable<T> source, bool condition, Func<IQueryable<T>, T0, T1, T2, T3, T4, T5, T6, T7, IQueryable<T>> query, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7)
62-
=> condition
63-
? query(source, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
64-
: source;
65-
}
1+
// ---------------------------------------------------------------------------------------------------------------------
2+
// Imports
3+
// ---------------------------------------------------------------------------------------------------------------------
4+
using System.Diagnostics;
5+
6+
namespace Microsoft.EntityFrameworkCore;
7+
// ---------------------------------------------------------------------------------------------------------------------
8+
// Code
9+
// ---------------------------------------------------------------------------------------------------------------------
10+
public static class LinqConditionalWithExtensions {
11+
12+
[DebuggerStepThrough]
13+
public static IQueryable<T> ConditionalWith<T>(this IQueryable<T> source, bool condition, Func<IQueryable<T>, IQueryable<T>> query)
14+
=> condition
15+
? query(source)
16+
: source;
17+
18+
[DebuggerStepThrough]
19+
public static IQueryable<T> ConditionalWith<T, T0>(this IQueryable<T> source, bool condition, Func<IQueryable<T>, T0, IQueryable<T>> query, T0 arg0)
20+
=> condition
21+
? query(source, arg0)
22+
: source;
23+
24+
[DebuggerStepThrough]
25+
public static IQueryable<T> ConditionalWith<T, T0, T1>(this IQueryable<T> source, bool condition, Func<IQueryable<T>, T0, T1, IQueryable<T>> query, T0 arg0, T1 arg1)
26+
=> condition
27+
? query(source, arg0, arg1)
28+
: source;
29+
30+
[DebuggerStepThrough]
31+
public static IQueryable<T> ConditionalWith<T, T0, T1, T2>(this IQueryable<T> source, bool condition, Func<IQueryable<T>, T0, T1, T2, IQueryable<T>> query, T0 arg0, T1 arg1, T2 arg2)
32+
=> condition
33+
? query(source, arg0, arg1, arg2)
34+
: source;
35+
36+
[DebuggerStepThrough]
37+
public static IQueryable<T> ConditionalWith<T, T0, T1, T2, T3>(this IQueryable<T> source, bool condition, Func<IQueryable<T>, T0, T1, T2, T3, IQueryable<T>> query, T0 arg0, T1 arg1, T2 arg2, T3 arg3)
38+
=> condition
39+
? query(source, arg0, arg1, arg2, arg3)
40+
: source;
41+
42+
[DebuggerStepThrough]
43+
public static IQueryable<T> ConditionalWith<T, T0, T1, T2, T3, T4>(this IQueryable<T> source, bool condition, Func<IQueryable<T>, T0, T1, T2, T3, T4, IQueryable<T>> query, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4)
44+
=> condition
45+
? query(source, arg0, arg1, arg2, arg3, arg4)
46+
: source;
47+
48+
[DebuggerStepThrough]
49+
public static IQueryable<T> ConditionalWith<T, T0, T1, T2, T3, T4, T5>(this IQueryable<T> source, bool condition, Func<IQueryable<T>, T0, T1, T2, T3, T4, T5, IQueryable<T>> query, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5)
50+
=> condition
51+
? query(source, arg0, arg1, arg2, arg3, arg4, arg5)
52+
: source;
53+
54+
[DebuggerStepThrough]
55+
public static IQueryable<T> ConditionalWith<T, T0, T1, T2, T3, T4, T5, T6>(this IQueryable<T> source, bool condition, Func<IQueryable<T>, T0, T1, T2, T3, T4, T5, T6, IQueryable<T>> query, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6)
56+
=> condition
57+
? query(source, arg0, arg1, arg2, arg3, arg4, arg5, arg6)
58+
: source;
59+
60+
[DebuggerStepThrough]
61+
public static IQueryable<T> ConditionalWith<T, T0, T1, T2, T3, T4, T5, T6, T7>(this IQueryable<T> source, bool condition, Func<IQueryable<T>, T0, T1, T2, T3, T4, T5, T6, T7, IQueryable<T>> query, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7)
62+
=> condition
63+
? query(source, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
64+
: source;
65+
}

0 commit comments

Comments
 (0)