diff --git a/src/MiniSkeletonAPI.Presentation/LocalDatabase.db-shm b/src/MiniSkeletonAPI.Presentation/LocalDatabase.db-shm
new file mode 100644
index 0000000..7cc364f
Binary files /dev/null and b/src/MiniSkeletonAPI.Presentation/LocalDatabase.db-shm differ
diff --git a/src/MiniSkeletonAPI.Presentation/LocalDatabase.db-wal b/src/MiniSkeletonAPI.Presentation/LocalDatabase.db-wal
new file mode 100644
index 0000000..132f01a
Binary files /dev/null and b/src/MiniSkeletonAPI.Presentation/LocalDatabase.db-wal differ
diff --git a/tests/Application.UnitTests/Application.UnitTests.csproj b/tests/Application.UnitTests/Application.UnitTests.csproj
new file mode 100644
index 0000000..581c183
--- /dev/null
+++ b/tests/Application.UnitTests/Application.UnitTests.csproj
@@ -0,0 +1,30 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/Application.UnitTests/Common/Behaviours/RequestLoggerTests.cs b/tests/Application.UnitTests/Common/Behaviours/RequestLoggerTests.cs
new file mode 100644
index 0000000..c641f7e
--- /dev/null
+++ b/tests/Application.UnitTests/Common/Behaviours/RequestLoggerTests.cs
@@ -0,0 +1,45 @@
+using MiniSkeletonAPI.Application.Common.Behaviours;
+using MiniSkeletonAPI.Application.Common.Interfaces;
+using MiniSkeletonAPI.Application.TodoItems.Commands.CreateTodoItem;
+using Microsoft.Extensions.Logging;
+using Moq;
+using NUnit.Framework;
+
+namespace Application.UnitTests.Common.Behaviours;
+
+public class RequestLoggerTests
+{
+ private Mock> _logger = null!;
+ private Mock _user = null!;
+ private Mock _identityService = null!;
+
+ [SetUp]
+ public void Setup()
+ {
+ _logger = new Mock>();
+ _user = new Mock();
+ _identityService = new Mock();
+ }
+
+ [Test]
+ public async Task ShouldCallGetUserNameAsyncOnceIfAuthenticated()
+ {
+ _user.Setup(x => x.Id).Returns(Guid.NewGuid().ToString());
+
+ var requestLogger = new LoggingBehaviour(_logger.Object, _user.Object, _identityService.Object);
+
+ await requestLogger.Process(new CreateTodoItemCommand { ListId = new Guid(), Title = "title" }, new CancellationToken());
+
+ _identityService.Verify(i => i.GetUserNameAsync(It.IsAny()), Times.Once);
+ }
+
+ [Test]
+ public async Task ShouldNotCallGetUserNameAsyncOnceIfUnauthenticated()
+ {
+ var requestLogger = new LoggingBehaviour(_logger.Object, _user.Object, _identityService.Object);
+
+ await requestLogger.Process(new CreateTodoItemCommand { ListId = new Guid(), Title = "title" }, new CancellationToken());
+
+ _identityService.Verify(i => i.GetUserNameAsync(It.IsAny()), Times.Never);
+ }
+}
diff --git a/tests/Application.UnitTests/Common/Exceptions/ValidationExceptionTests.cs b/tests/Application.UnitTests/Common/Exceptions/ValidationExceptionTests.cs
new file mode 100644
index 0000000..ace0090
--- /dev/null
+++ b/tests/Application.UnitTests/Common/Exceptions/ValidationExceptionTests.cs
@@ -0,0 +1,55 @@
+using MiniSkeletonAPI.Application.Common.Exceptions;
+using FluentAssertions;
+using FluentValidation.Results;
+using NUnit.Framework;
+
+namespace Application.UnitTests.Common.Exceptions;
+
+public class ValidationExceptionTests
+{
+ [Test]
+ public void DefaultConstructorCreatesAnEmptyErrorDictionary()
+ {
+ var actual = new ValidationException().Errors;
+
+ actual.Keys.Should().BeEquivalentTo(Array.Empty());
+ }
+
+ [Test]
+ public void SingleValidationFailureCreatesASingleElementErrorDictionary()
+ {
+ var failures = new List
+ {
+ new ValidationFailure("Password", "must contain at least 8 characters"),
+ };
+
+ var actual = new ValidationException(failures).Errors;
+
+ actual.Keys.Should().BeEquivalentTo(new string[] { "Password" });
+ actual["Password"].Should().BeEquivalentTo(new string[] { "must contain at least 8 characters" });
+ }
+
+ [Test]
+ public void MulitpleValidationFailureForMultiplePropertiesCreatesAMultipleElementErrorDictionaryEachWithMultipleValues()
+ {
+ var failures = new List
+ {
+ new ValidationFailure("Password", "must contain at least 8 characters"),
+ new ValidationFailure("Password", "must contain a digit"),
+ new ValidationFailure("Password", "must contain upper case letter"),
+ new ValidationFailure("Password", "must contain lower case letter"),
+ };
+
+ var actual = new ValidationException(failures).Errors;
+
+ actual.Keys.Should().BeEquivalentTo(new string[] { "Password" });
+
+ actual["Password"].Should().BeEquivalentTo(new string[]
+ {
+ "must contain lower case letter",
+ "must contain upper case letter",
+ "must contain at least 8 characters",
+ "must contain a digit",
+ });
+ }
+}
diff --git a/tests/Application.UnitTests/Common/Mappings/MappingTests.cs b/tests/Application.UnitTests/Common/Mappings/MappingTests.cs
new file mode 100644
index 0000000..36e0400
--- /dev/null
+++ b/tests/Application.UnitTests/Common/Mappings/MappingTests.cs
@@ -0,0 +1,53 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using AutoMapper;
+using MiniSkeletonAPI.Application.Common.Interfaces;
+using MiniSkeletonAPI.Application.Common.Models;
+using MiniSkeletonAPI.Application.TodoItems.Queries.GetTodoItemsWithPagination;
+using MiniSkeletonAPI.Application.TodoLists.Queries.GetTodos;
+using MiniSkeletonAPI.Domain.Entities;
+using NUnit.Framework;
+
+namespace Application.UnitTests.Common.Mappings;
+
+public class MappingTests
+{
+ private readonly IConfigurationProvider _configuration;
+ private readonly IMapper _mapper;
+
+ public MappingTests()
+ {
+ _configuration = new MapperConfiguration(config =>
+ config.AddMaps(Assembly.GetAssembly(typeof(IApplicationDbContext))));
+
+ _mapper = _configuration.CreateMapper();
+ }
+
+ [Test]
+ public void ShouldHaveValidConfiguration()
+ {
+ _configuration.AssertConfigurationIsValid();
+ }
+
+ [Test]
+ [TestCase(typeof(TodoList), typeof(TodoListDto))]
+ [TestCase(typeof(TodoItem), typeof(TodoItemDto))]
+ [TestCase(typeof(TodoList), typeof(LookupDto))]
+ [TestCase(typeof(TodoItem), typeof(LookupDto))]
+ [TestCase(typeof(TodoItem), typeof(TodoItemBriefDto))]
+ public void ShouldSupportMappingFromSourceToDestination(Type source, Type destination)
+ {
+ var instance = GetInstanceOf(source);
+
+ _mapper.Map(instance, source, destination);
+ }
+
+ private object GetInstanceOf(Type type)
+ {
+ if (type.GetConstructor(Type.EmptyTypes) != null)
+ return Activator.CreateInstance(type)!;
+
+ // Type without parameterless constructor
+ return RuntimeHelpers.GetUninitializedObject(type);
+ }
+}
diff --git a/tests/Application.UnitTests/UnitTest1.cs b/tests/Application.UnitTests/UnitTest1.cs
new file mode 100644
index 0000000..f582c5f
--- /dev/null
+++ b/tests/Application.UnitTests/UnitTest1.cs
@@ -0,0 +1,16 @@
+namespace Application.UnitTests
+{
+ public class Tests
+ {
+ [SetUp]
+ public void Setup()
+ {
+ }
+
+ [Test]
+ public void Test1()
+ {
+ Assert.Pass();
+ }
+ }
+}
\ No newline at end of file