Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions SqlOnly/Blog.Tests.Integration/Blog.Tests.Integration.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
<ItemGroup>
<PackageReference Include="Accelergreat.EntityFramework.SqlServer" Version="1.3.6" />
<PackageReference Include="Accelergreat.Xunit" Version="1.3.6" />
<PackageReference Include="AutoFixture" Version="4.18.0" />
<PackageReference Include="AutoFixture.AutoNSubstitute" Version="4.18.0" />
<PackageReference Include="AutoFixture.Xunit2" Version="4.18.0" />
<PackageReference Include="FluentAssertions" Version="6.7.0" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using AutoFixture;
using AutoFixture.AutoNSubstitute;
using AutoFixture.Xunit2;

namespace Blog.Tests.Integration.Customisation;

public class AutoNSubstituteDataAttribute : AutoDataAttribute
{
public AutoNSubstituteDataAttribute(params Type[] optionalCustomizationTypes)
: base(() => BuildFixture(optionalCustomizationTypes))
{
}

// ReSharper disable once ParameterTypeCanBeEnumerable.Local
private static IFixture BuildFixture(Type[] optionalCustomizationTypes)
{
var fixture = new Fixture()
.Customize(new AutoNSubstituteCustomization());

foreach (var customizationType in optionalCustomizationTypes)
{
fixture.Customize((ICustomization)Activator.CreateInstance(customizationType));
}

return fixture;
}
}
25 changes: 25 additions & 0 deletions SqlOnly/Blog.Tests.Integration/Extensions/ReflectionExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#nullable enable
using System.Reflection;

namespace Blog.Tests.Integration.Extensions;

public static class ReflectionExtensions
{
public static T SetThroughReflection<T>(this T entity, string propertyName, object? value)
{
var properties = typeof(T).GetProperties(BindingFlags.FlattenHierarchy |
BindingFlags.Instance |
BindingFlags.Public).ToArray();

var named = properties.Where(x => x.Name == propertyName).ToArray();

var property = typeof(T).GetProperties(BindingFlags.FlattenHierarchy |
BindingFlags.Instance |
BindingFlags.Public)
.Single(s => s.SetMethod != null && s.Name == propertyName);

property.SetValue(entity, value);

return entity;
}
}
35 changes: 33 additions & 2 deletions SqlOnly/Blog.Tests.Integration/Services/BlogServiceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
using Blog.Data;
using Blog.Data.Entities;
using Blog.Services;
using Blog.Tests.Integration.Customisation;
using Blog.Tests.Integration.Extensions;
using FluentAssertions;
using Microsoft.EntityFrameworkCore;
using Xunit;
Expand All @@ -29,11 +31,11 @@ public async Task Inserts_a_Post()
{
var title = "A test post";
var text = "This post was made in an integration test and was saved to a SQL instance managed by Accelergreat.";

var user = GetComponent<BlogSqlAccelergreatComponent>().Users.First();

await using var testContext = CreateContext();

var service = new BlogService(testContext);

var resultingPost = await service.CreatePost(user.UserId, title, text);
Expand Down Expand Up @@ -80,4 +82,33 @@ public async Task Inserts_a_Comment()
databasePost.PostId.Should().Be(post.PostId);
databasePost.Text.Should().Be(text);
}

[Theory, AutoNSubstituteData]
public async Task Inserts_a_Post_from__AutoFixture(Post post)
{
var user = GetComponent<BlogSqlAccelergreatComponent>().Users.First();

post.SetThroughReflection(nameof(Post.UserId), user.UserId);

await using var testContext = CreateContext();

var service = new BlogService(testContext);

var resultingPost = await service.CreatePost(post);

// Assert the result from the service is as expected
resultingPost.UserId.Should().Be(user.UserId);
resultingPost.Title.Should().Be(post.Title);
resultingPost.Text.Should().Be(post.Text);

// Assert the data stored to the database is as expected
// This is done on a separate DbContext to ensure in-memory instances are not used
await using var assertionContext = CreateContext();
var databasePost = await assertionContext.Set<Post>().SingleAsync(x => x.PostId == resultingPost.PostId);

databasePost.UserId.Should().Be(user.UserId);
databasePost.Title.Should().Be(post.Title);
databasePost.Text.Should().Be(post.Text);
}

}
5 changes: 5 additions & 0 deletions SqlOnly/Blog/Services/BlogService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ public async Task<Post> CreatePost(int userId, string title, string text)
{
var post = new Post(userId, title, text);

return await CreatePost(post);
}

public async Task<Post> CreatePost(Post post)
{
_dbContext.Set<Post>().Add(post);

await _dbContext.SaveChangesAsync();
Expand Down