Skip to content

Commit da05527

Browse files
authored
Redesigned library (#111)
* Removed the custom request specifications * Removed custom in-memory options specimen builder * Replaced sqlite options specimen builder with type relay * Removed custom sqlite connection builder * Added connection string configuration option * Redesigned the provider customizations * Working draft * Removed unused types * Added tests for context options builder and base customization * Added more tests * Increased coverage to 100% * Added dedicated checks type * Added documentation comments * Split up tests into specialized files
1 parent e680524 commit da05527

File tree

114 files changed

+3505
-2416
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

114 files changed

+3505
-2416
lines changed

.editorconfig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ dotnet_naming_rule.members_should_be_pascal_case.style = pascal_case_style
137137
dotnet_naming_symbols.all_members.applicable_kinds = *
138138

139139
dotnet_naming_style.pascal_case_style.capitalization = pascal_case
140-
dotnet_style_operator_placement_when_wrapping=beginning_of_line
140+
dotnet_style_operator_placement_when_wrapping = beginning_of_line
141141

142142
# CSharp code style settings:
143143
[*.cs]
@@ -205,6 +205,6 @@ csharp_space_between_parentheses = false
205205
csharp_space_between_square_brackets = false
206206

207207
# Blocks are allowed
208-
csharp_prefer_braces =when_multiline:warning
208+
csharp_prefer_braces = when_multiline:warning
209209
csharp_preserve_single_line_blocks = true
210210
csharp_preserve_single_line_statements = true

Common.Tests.props

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@
77
</PropertyGroup>
88

99
<ItemGroup>
10-
<PackageReference Include="FluentAssertions" Version="5.10.3" />
11-
<PackageReference Include="FluentAssertions.Analyzers" Version="0.11.4" />
10+
<PackageReference Include="FluentAssertions" Version="5.10.3"/>
11+
<PackageReference Include="FluentAssertions.Analyzers" Version="0.11.4"/>
1212

13-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
13+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1"/>
1414

15-
<PackageReference Include="xunit" Version="2.4.1" />
15+
<PackageReference Include="xunit" Version="2.4.1"/>
1616
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
1717
<PrivateAssets>all</PrivateAssets>
1818
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

Common.props

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
<RepositoryType>git</RepositoryType>
1212

1313
<PackageIcon>icon.png</PackageIcon>
14-
<PackageReadmeFile>readme.md</PackageReadmeFile>
14+
<PackageReadmeFile>readme.md</PackageReadmeFile>
1515

1616
<!-- Publish the repository URL in the built .nupkg (in the NuSpec <Repository> element) -->
1717
<PublishRepositoryUrl>true</PublishRepositoryUrl>
@@ -22,11 +22,11 @@
2222

2323
<ItemGroup>
2424
<!-- <SourceRoot Include="$(MSBuildThisFileDirectory)/"/> -->
25-
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="all" />
25+
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="all"/>
2626
</ItemGroup>
2727

2828
<ItemGroup>
29-
<None Include="..\..\readme.md" Pack="true" PackagePath="\" />
30-
<None Include="..\..\icon.png" Pack="true" PackagePath="\" />
29+
<None Include="..\..\readme.md" Pack="true" PackagePath="\"/>
30+
<None Include="..\..\icon.png" Pack="true" PackagePath="\"/>
3131
</ItemGroup>
3232
</Project>

GitVersion.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ branches:
66
tag: ''
77
increment: Patch
88
release:
9-
source-branches: ['master']
9+
source-branches: [ 'master' ]
1010
prevent-increment-of-merged-branch-version: true
1111
tag: 'preview'
1212
ignore:
13-
sha: []
14-
merge-message-formats: {}
13+
sha: [ ]
14+
merge-message-formats: { }

README.md

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,33 +6,49 @@
66
[![Nuget](https://img.shields.io/nuget/v/EntityFrameworkCore.AutoFixture?logo=nuget&style=flat-square)](https://www.nuget.org/packages/EntityFrameworkCore.AutoFixture/)
77
[![GitHub](https://img.shields.io/github/license/aivascu/EntityFrameworkCore.AutoFixture?logo=MIT&style=flat-square)](https://licenses.nuget.org/MIT)
88

9-
**EntityFrameworkCore.AutoFixture** is the logical product of [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) in-memory providers and [AutoFixture](https://github.com/AutoFixture/AutoFixture).
9+
**EntityFrameworkCore.AutoFixture** is the logical product
10+
of [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) in-memory providers
11+
and [AutoFixture](https://github.com/AutoFixture/AutoFixture).
1012

11-
Using **EntityFrameworkCore.AutoFixture** you can greatly reduce the boilerplate work necessary to unit test code that uses **Entity Framework Core** database contexts (see [examples](#examples)). You'll appreciate this library if you are already using **AutoFixture** as your auto-mocking container.
13+
Using **EntityFrameworkCore.AutoFixture** you can greatly reduce the boilerplate work necessary to unit test code that
14+
uses **Entity Framework Core** database contexts (see [examples](#examples)). You'll appreciate this library if you are
15+
already using **AutoFixture** as your auto-mocking container.
1216

13-
**EntityFrameworkCore.AutoFixture** extens **AutoFixture** with the ability to create fully functional `DbContext` instances, with very little setup code.
17+
**EntityFrameworkCore.AutoFixture** extens **AutoFixture** with the ability to create fully functional `DbContext`
18+
instances, with very little setup code.
1419

15-
Unlike other libraries for faking EF contexts, **EntityFrameworkCore.AutoFixture** does not use mocking frameworks or dynamic proxies in order to create `DbContext` instances, instead it uses the Microsoft's own in-memory [providers](https://docs.microsoft.com/en-us/ef/core/miscellaneous/testing/) for EF Core. This allows to make less assumptions (read as: mock setups) in your tests about how the `DbContext` will behave in the real environment.
20+
Unlike other libraries for faking EF contexts, **EntityFrameworkCore.AutoFixture** does not use mocking frameworks or
21+
dynamic proxies in order to create `DbContext` instances, instead it uses the Microsoft's own
22+
in-memory [providers](https://docs.microsoft.com/en-us/ef/core/miscellaneous/testing/) for EF Core. This allows to make
23+
less assumptions (read as: mock setups) in your tests about how the `DbContext` will behave in the real environment.
1624

1725
#### :warning: .NET Standard 2.0 in EF Core v3.0.x :warning:
1826

19-
Entity Framework Core `v3.0.0` - `v3.0.3` are targeting `netstandard2.1`, which means they are not compatible with target frameworks that support at most `netstandard2.0` (`>= net47` and `netcoreapp2.1`).
20-
Versions after `v3.1` are targeting `netstandard2.0`. If you've encountered this issue consider upgrading to a later version of Entity Framework Core.
27+
Entity Framework Core `v3.0.0` - `v3.0.3` are targeting `netstandard2.1`, which means they are not compatible with
28+
target frameworks that support at most `netstandard2.0` (`>= net47` and `netcoreapp2.1`).
29+
Versions after `v3.1` are targeting `netstandard2.0`. If you've encountered this issue consider upgrading to a later
30+
version of Entity Framework Core.
2131

2232
## Features
2333

2434
**EntityFrameworkCore.AutoFixture** offers three customizations to aid your unit testing workflow:
2535

26-
- `InMemoryContextCustomization` - customizes fixtures to use the In-Memory database provider when creating *DbContext* instances
27-
- `SqliteContextCustomization` - customizes fixtures to use the SQLite database provider when creating *DbContext* instances.
28-
By default the customization will create contexts for an in-memory *connection string* (i.e. `DataSource=:memory:`). This can be changed by providing the fixture a predefined `SqliteConnection` instance.
29-
- `DbContextCustomization` - serves as the base customization for the other two implementations. The customization can be used, in more advanced scenarios, when you want to extend the fixtures with your own specimen builders.
36+
- `InMemoryContextCustomization` - customizes fixtures to use the In-Memory database provider when creating *DbContext*
37+
instances
38+
- `SqliteContextCustomization` - customizes fixtures to use the SQLite database provider when creating *DbContext*
39+
instances.
40+
By default the customization will create contexts for an in-memory *connection string* (i.e. `DataSource=:memory:`).
41+
This can be changed by providing the fixture a predefined `SqliteConnection` instance.
42+
- `DbContextCustomization` - serves as the base customization for the other two implementations. The customization can
43+
be used, in more advanced scenarios, when you want to extend the fixtures with your own specimen builders.
3044

3145
## Examples
3246

33-
The examples below demonstrate, the possible ways of using the library in [xUnit](https://github.com/xunit/xunit) test projects, both with `[Fact]` and `[Theory]` tests.
47+
The examples below demonstrate, the possible ways of using the library in [xUnit](https://github.com/xunit/xunit) test
48+
projects, both with `[Fact]` and `[Theory]` tests.
3449

35-
The library is not limited to `xUnit` and can be used with other testing frameworks like `NUnit` and `MSTest`, since it only provides a few `Customization` implementations.
50+
The library is not limited to `xUnit` and can be used with other testing frameworks like `NUnit` and `MSTest`, since it
51+
only provides a few `Customization` implementations.
3652

3753
### Using In-Memory database provider
3854

@@ -57,7 +73,8 @@ public async Task CanUseGeneratedContext()
5773
}
5874
```
5975

60-
The next example uses a custom `AutoData` attribute `AutoDomainDataWithInMemoryContext` that customizes the fixture with the same customization as in the example above. This helps abstract away even more setup code.
76+
The next example uses a custom `AutoData` attribute `AutoDomainDataWithInMemoryContext` that customizes the fixture with
77+
the same customization as in the example above. This helps abstract away even more setup code.
6178

6279
```csharp
6380
[Theory, InMemoryData]
@@ -71,6 +88,7 @@ public async Task CanUseGeneratedContext(TestDbContext context)
7188
context.Customers.Should().Contain(x => x.Name == "Jane Smith");
7289
}
7390
```
91+
7492
The attribute used in the test above might look something like the following.
7593

7694
```csharp
@@ -87,9 +105,12 @@ public class InMemoryDataAttribute : AutoDataAttribute
87105
}
88106
}
89107
```
108+
90109
### Using SQLite database provider
91110

92-
When using the SQLite database provider there is another configuration available in the customization, called `AutoOpenConnection` which allows to automatically open database connections, after they are resolved from the fixture. The option is turned off by default in v1, but might become the default in next major releases.
111+
When using the SQLite database provider there is another configuration available in the customization,
112+
called `AutoOpenConnection` which allows to automatically open database connections, after they are resolved from the
113+
fixture. The option is turned off by default in v1, but might become the default in next major releases.
93114

94115
```csharp
95116
[Fact]

global.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"sdk": {
3-
"version": "6.0.100",
4-
"rollForward": "latestFeature"
3+
"version": "6.0.100",
4+
"rollForward": "latestFeature"
55
}
66
}
Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,41 @@
1-
using System;
1+
using System;
22
using AutoFixture.Kernel;
33

4-
namespace EntityFrameworkCore.AutoFixture.Core
4+
namespace EntityFrameworkCore.AutoFixture.Core;
5+
6+
/// <summary>
7+
/// Checks whether a type is assignable to the base type.
8+
/// </summary>
9+
public class BaseTypeSpecification : IRequestSpecification
510
{
6-
public class BaseTypeSpecification : IRequestSpecification
11+
/// <summary>
12+
/// Creates an instance of type <see cref="BaseTypeSpecification"/>.
13+
/// </summary>
14+
/// <param name="type">The base type.</param>
15+
/// <exception cref="ArgumentNullException">Thrown when <param name="type" /> is <see langword="null"/>.</exception>
16+
public BaseTypeSpecification(Type type)
717
{
8-
public BaseTypeSpecification(Type baseType)
9-
{
10-
this.BaseType = baseType
11-
?? throw new ArgumentNullException(nameof(baseType));
12-
}
18+
Check.NotNull(type, nameof(type));
19+
20+
this.Type = type;
21+
}
1322

14-
public Type BaseType { get; }
23+
/// <summary>
24+
/// Gets the base type.
25+
/// </summary>
26+
public Type Type { get; }
1527

16-
public bool IsSatisfiedBy(object request)
17-
{
18-
return request is Type type
19-
&& this.BaseType.IsAssignableFrom(type);
20-
}
28+
/// <summary>
29+
/// Checks if the request is a <see cref="Type"/> and it is assignable to the base type.
30+
/// </summary>
31+
/// <param name="request">The request to be validated.</param>
32+
/// <returns>
33+
/// When the request is a type assignable to te base type, returns <see langword="true"/>.
34+
/// Otherwise returns <see langword="false"/>
35+
/// </returns>
36+
public bool IsSatisfiedBy(object request)
37+
{
38+
return request is Type type
39+
&& this.Type.IsAssignableFrom(type);
2140
}
2241
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
using System;
2+
3+
namespace EntityFrameworkCore.AutoFixture.Core;
4+
5+
/// <summary>
6+
/// Implements argument validation checks.
7+
/// </summary>
8+
public static class Check
9+
{
10+
/// <summary>
11+
/// Validates if <paramref name="value" /> is of type <typeparamref name="T" />.
12+
/// </summary>
13+
/// <param name="value">The value to be validated.</param>
14+
/// <param name="paramName">The parameter name.</param>
15+
/// <typeparam name="T">The target type.</typeparam>
16+
/// <returns>
17+
/// Returns an instance of type <typeparamref name="T" /> if <paramref name="value" /> matches the target type.
18+
/// </returns>
19+
/// <exception cref="ArgumentException">
20+
/// Thrown when <paramref name="value" /> is not of type <typeparamref name="T" />.
21+
/// </exception>
22+
/// <exception cref="ArgumentNullException">
23+
/// Thrown when <paramref name="value" /> is <see langword="null"/>.
24+
/// </exception>
25+
public static T IsOfType<T>(object value, string paramName)
26+
{
27+
if (value is null)
28+
throw new ArgumentNullException(paramName);
29+
30+
if (value is not T result)
31+
{
32+
throw new ArgumentException(
33+
$"Argument expected to be of type \"{typeof(T)}\", but was \"{value.GetType()}\".",
34+
paramName);
35+
}
36+
37+
return result;
38+
}
39+
40+
/// <summary>
41+
/// Validates if <paramref name="value" /> is <see langword="null"/>.
42+
/// </summary>
43+
/// <param name="value">The value to be validated.</param>
44+
/// <param name="paramName">The parameter name.</param>
45+
/// <exception cref="ArgumentNullException">
46+
/// Thrown when <paramref name="value" /> is <see langword="null"/>.
47+
/// </exception>
48+
public static void NotNull(object value, string paramName)
49+
{
50+
if (value is null)
51+
throw new ArgumentNullException(paramName);
52+
}
53+
54+
/// <summary>
55+
/// Validates if <paramref name="value" /> is <see langword="null"/> or an empty string.
56+
/// </summary>
57+
/// <param name="value">The value to be validated.</param>
58+
/// <param name="paramName">The parameter name.</param>
59+
/// <exception cref="ArgumentNullException">
60+
/// Thrown when <paramref name="value" /> is <see langword="null"/>.
61+
/// </exception>
62+
/// <exception cref="ArgumentException">
63+
/// Thrown when <paramref name="value" /> is an empty string.
64+
/// </exception>
65+
public static void NotEmpty(string value, string paramName)
66+
{
67+
if (value is null)
68+
throw new ArgumentNullException(paramName);
69+
70+
if (value.Trim().Length == 0)
71+
throw new ArgumentException("Value cannot be empty.", paramName);
72+
}
73+
}

src/EntityFrameworkCore.AutoFixture/Core/ConnectionOpeningBehavior.cs

Lines changed: 0 additions & 20 deletions
This file was deleted.

src/EntityFrameworkCore.AutoFixture/Core/ConnectionOpeningNode.cs

Lines changed: 0 additions & 45 deletions
This file was deleted.

0 commit comments

Comments
 (0)