diff --git a/SqlOnly/Blog.Tests.Integration/Blog.Tests.Integration.csproj b/SqlOnly/Blog.Tests.Integration/Blog.Tests.Integration.csproj
index eb26106..9058ca2 100644
--- a/SqlOnly/Blog.Tests.Integration/Blog.Tests.Integration.csproj
+++ b/SqlOnly/Blog.Tests.Integration/Blog.Tests.Integration.csproj
@@ -9,6 +9,9 @@
+
+
+
diff --git a/SqlOnly/Blog.Tests.Integration/Customisation/AutoNSubstitudeDataAttribute.cs b/SqlOnly/Blog.Tests.Integration/Customisation/AutoNSubstitudeDataAttribute.cs
new file mode 100644
index 0000000..132c2fc
--- /dev/null
+++ b/SqlOnly/Blog.Tests.Integration/Customisation/AutoNSubstitudeDataAttribute.cs
@@ -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;
+ }
+}
\ No newline at end of file
diff --git a/SqlOnly/Blog.Tests.Integration/Extensions/ReflectionExtensions.cs b/SqlOnly/Blog.Tests.Integration/Extensions/ReflectionExtensions.cs
new file mode 100644
index 0000000..ea39296
--- /dev/null
+++ b/SqlOnly/Blog.Tests.Integration/Extensions/ReflectionExtensions.cs
@@ -0,0 +1,25 @@
+#nullable enable
+using System.Reflection;
+
+namespace Blog.Tests.Integration.Extensions;
+
+public static class ReflectionExtensions
+{
+ public static T SetThroughReflection(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;
+ }
+}
\ No newline at end of file
diff --git a/SqlOnly/Blog.Tests.Integration/Services/BlogServiceTests.cs b/SqlOnly/Blog.Tests.Integration/Services/BlogServiceTests.cs
index 3324356..4a0a7f0 100644
--- a/SqlOnly/Blog.Tests.Integration/Services/BlogServiceTests.cs
+++ b/SqlOnly/Blog.Tests.Integration/Services/BlogServiceTests.cs
@@ -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;
@@ -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().Users.First();
await using var testContext = CreateContext();
-
+
var service = new BlogService(testContext);
var resultingPost = await service.CreatePost(user.UserId, title, text);
@@ -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().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().SingleAsync(x => x.PostId == resultingPost.PostId);
+
+ databasePost.UserId.Should().Be(user.UserId);
+ databasePost.Title.Should().Be(post.Title);
+ databasePost.Text.Should().Be(post.Text);
+ }
+
}
\ No newline at end of file
diff --git a/SqlOnly/Blog/Services/BlogService.cs b/SqlOnly/Blog/Services/BlogService.cs
index 30310bc..b038aa0 100644
--- a/SqlOnly/Blog/Services/BlogService.cs
+++ b/SqlOnly/Blog/Services/BlogService.cs
@@ -16,6 +16,11 @@ public async Task CreatePost(int userId, string title, string text)
{
var post = new Post(userId, title, text);
+ return await CreatePost(post);
+ }
+
+ public async Task CreatePost(Post post)
+ {
_dbContext.Set().Add(post);
await _dbContext.SaveChangesAsync();