diff --git a/Directory.Packages.props b/Directory.Packages.props index 7a1298a..b7ca5fa 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -20,5 +20,14 @@ + + + + + + + + + diff --git a/VerticalSliceArchitecture.sln b/VerticalSliceArchitecture.sln index cb1788b..d39c481 100644 --- a/VerticalSliceArchitecture.sln +++ b/VerticalSliceArchitecture.sln @@ -14,6 +14,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution README.md = README.md EndProjectSection EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{5F44F0AC-5482-4A73-9CAE-6A550E23B510}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Application.UnitTests", "tests\Application.UnitTests\Application.UnitTests.csproj", "{24BF57AE-47C4-4065-BAB0-72ACB562D22E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -32,6 +36,10 @@ Global {22454EE9-16B3-4B7A-8352-37E59B858155}.Debug|Any CPU.Build.0 = Debug|Any CPU {22454EE9-16B3-4B7A-8352-37E59B858155}.Release|Any CPU.ActiveCfg = Release|Any CPU {22454EE9-16B3-4B7A-8352-37E59B858155}.Release|Any CPU.Build.0 = Release|Any CPU + {24BF57AE-47C4-4065-BAB0-72ACB562D22E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {24BF57AE-47C4-4065-BAB0-72ACB562D22E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {24BF57AE-47C4-4065-BAB0-72ACB562D22E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {24BF57AE-47C4-4065-BAB0-72ACB562D22E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -39,6 +47,7 @@ Global GlobalSection(NestedProjects) = preSolution {34C0FACD-F3D9-400C-8945-554DD6B0819A} = {6ED356A7-8B47-4613-AD01-C85CF28491BD} {22454EE9-16B3-4B7A-8352-37E59B858155} = {6ED356A7-8B47-4613-AD01-C85CF28491BD} + {24BF57AE-47C4-4065-BAB0-72ACB562D22E} = {5F44F0AC-5482-4A73-9CAE-6A550E23B510} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {3CB609D9-5D54-4C11-A371-DAAC8B74E430} diff --git a/tests/Application.UnitTests/Application.UnitTests.csproj b/tests/Application.UnitTests/Application.UnitTests.csproj index c4aac64..c7c97f0 100644 --- a/tests/Application.UnitTests/Application.UnitTests.csproj +++ b/tests/Application.UnitTests/Application.UnitTests.csproj @@ -1,28 +1,28 @@  - - net7.0 - VerticalSliceArchitecture.Application.UnitTests - VerticalSliceArchitecture.Application.UnitTests + + false + true + - false - enable - enable - + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - + + diff --git a/tests/Application.UnitTests/Common/Behaviours/RequestLoggerTests.cs b/tests/Application.UnitTests/Common/Behaviours/RequestLoggerTests.cs index b0e52f5..c335e88 100644 --- a/tests/Application.UnitTests/Common/Behaviours/RequestLoggerTests.cs +++ b/tests/Application.UnitTests/Common/Behaviours/RequestLoggerTests.cs @@ -1,39 +1,39 @@ -using VerticalSliceArchitecture.Application.Common.Behaviours; -using VerticalSliceArchitecture.Application.Common.Interfaces; -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; + using Moq; -using NUnit.Framework; + +using VerticalSliceArchitecture.Application.Common.Behaviours; +using VerticalSliceArchitecture.Application.Common.Interfaces; using VerticalSliceArchitecture.Application.Features.TodoItems; namespace VerticalSliceArchitecture.Application.UnitTests.Common.Behaviours; public class RequestLoggerTests { - private Mock> _logger = null!; - private Mock _currentUserService = null!; + private readonly Mock> _logger; + private readonly Mock _currentUserService; - [SetUp] - public void Setup() + public RequestLoggerTests() { _logger = new Mock>(); _currentUserService = new Mock(); } - [Test] + [Fact] public async Task ShouldCallGetUserNameAsyncOnceIfAuthenticated() { _currentUserService.Setup(x => x.UserId).Returns(Guid.NewGuid().ToString()); var requestLogger = new LoggingBehaviour(_logger.Object, _currentUserService.Object); - await requestLogger.Process(new CreateTodoItemCommand { ListId = 1, Title = "title" }, new CancellationToken()); + await requestLogger.Process(new CreateTodoItemCommand { ListId = 1, Title = "title" }, CancellationToken.None); } - [Test] + [Fact] public async Task ShouldNotCallGetUserNameAsyncOnceIfUnauthenticated() { var requestLogger = new LoggingBehaviour(_logger.Object, _currentUserService.Object); - await requestLogger.Process(new CreateTodoItemCommand { ListId = 1, Title = "title" }, new CancellationToken()); + await requestLogger.Process(new CreateTodoItemCommand { ListId = 1, Title = "title" }, CancellationToken.None); } } diff --git a/tests/Application.UnitTests/Common/Exceptions/ValidationExceptionTests.cs b/tests/Application.UnitTests/Common/Exceptions/ValidationExceptionTests.cs index 9c26392..3900c6e 100644 --- a/tests/Application.UnitTests/Common/Exceptions/ValidationExceptionTests.cs +++ b/tests/Application.UnitTests/Common/Exceptions/ValidationExceptionTests.cs @@ -1,13 +1,12 @@ -using VerticalSliceArchitecture.Application.Common.Exceptions; -using FluentAssertions; -using FluentValidation.Results; -using NUnit.Framework; +using FluentValidation.Results; + +using VerticalSliceArchitecture.Application.Common.Exceptions; namespace VerticalSliceArchitecture.Application.UnitTests.Common.Exceptions; public class ValidationExceptionTests { - [Test] + [Fact] public void DefaultConstructorCreatesAnEmptyErrorDictionary() { var actual = new ValidationException().Errors; @@ -15,12 +14,12 @@ public void DefaultConstructorCreatesAnEmptyErrorDictionary() actual.Keys.Should().BeEquivalentTo(Array.Empty()); } - [Test] + [Fact] public void SingleValidationFailureCreatesASingleElementErrorDictionary() { var failures = new List { - new ValidationFailure("Age", "must be over 18"), + new("Age", "must be over 18"), }; var actual = new ValidationException(failures).Errors; @@ -29,17 +28,17 @@ public void SingleValidationFailureCreatesASingleElementErrorDictionary() actual["Age"].Should().BeEquivalentTo(new string[] { "must be over 18" }); } - [Test] + [Fact] public void MulitpleValidationFailureForMultiplePropertiesCreatesAMultipleElementErrorDictionaryEachWithMultipleValues() { var failures = new List { - new ValidationFailure("Age", "must be 18 or older"), - new ValidationFailure("Age", "must be 25 or younger"), - 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"), + new("Age", "must be 18 or older"), + new("Age", "must be 25 or younger"), + new("Password", "must contain at least 8 characters"), + new("Password", "must contain a digit"), + new("Password", "must contain upper case letter"), + new("Password", "must contain lower case letter"), }; var actual = new ValidationException(failures).Errors; diff --git a/tests/Application.UnitTests/Common/Mappings/MappingTests.cs b/tests/Application.UnitTests/Common/Mappings/MappingTests.cs index 6fff75f..a502aea 100644 --- a/tests/Application.UnitTests/Common/Mappings/MappingTests.cs +++ b/tests/Application.UnitTests/Common/Mappings/MappingTests.cs @@ -1,7 +1,6 @@ -using System.Runtime.Serialization; -using AutoMapper; +using AutoMapper; + using VerticalSliceArchitecture.Application.Common.Mappings; -using NUnit.Framework; using VerticalSliceArchitecture.Application.Domain.Todos; using VerticalSliceArchitecture.Application.Features.TodoLists; @@ -20,15 +19,15 @@ public MappingTests() _mapper = _configuration.CreateMapper(); } - [Test] + [Fact] public void ShouldHaveValidConfiguration() { _configuration.AssertConfigurationIsValid(); } - [Test] - [TestCase(typeof(TodoList), typeof(TodoListDto))] - [TestCase(typeof(TodoItem), typeof(TodoItemDto))] + [Theory] + [InlineData(typeof(TodoList), typeof(TodoListDto))] + [InlineData(typeof(TodoItem), typeof(TodoItemDto))] public void ShouldSupportMappingFromSourceToDestination(Type source, Type destination) { var instance = GetInstanceOf(source); @@ -36,12 +35,8 @@ public void ShouldSupportMappingFromSourceToDestination(Type source, Type destin _mapper.Map(instance, source, destination); } - private object GetInstanceOf(Type type) + private static object GetInstanceOf(Type type) { - if (type.GetConstructor(Type.EmptyTypes) != null) - return Activator.CreateInstance(type)!; - - // Type without parameterless constructor - return FormatterServices.GetUninitializedObject(type); + return Activator.CreateInstance(type)!; } } diff --git a/tests/Application.UnitTests/GlobalUsings.cs b/tests/Application.UnitTests/GlobalUsings.cs new file mode 100644 index 0000000..168410c --- /dev/null +++ b/tests/Application.UnitTests/GlobalUsings.cs @@ -0,0 +1,3 @@ +global using FluentAssertions; + +global using Xunit; \ No newline at end of file diff --git a/tests/Application.UnitTests/ValueObjects/ColourTests.cs b/tests/Application.UnitTests/ValueObjects/ColourTests.cs index c6b1407..3493088 100644 --- a/tests/Application.UnitTests/ValueObjects/ColourTests.cs +++ b/tests/Application.UnitTests/ValueObjects/ColourTests.cs @@ -1,15 +1,11 @@ -using FluentAssertions; - -using NUnit.Framework; - -using VerticalSliceArchitecture.Application.Common.Exceptions; +using VerticalSliceArchitecture.Application.Common.Exceptions; using VerticalSliceArchitecture.Application.Domain.ValueObjects; namespace VerticalSliceArchitecture.Application.UnitTests.ValueObjects; public class ColourTests { - [Test] + [Fact] public void ShouldReturnCorrectColourCode() { var code = "#FFFFFF"; @@ -19,7 +15,7 @@ public void ShouldReturnCorrectColourCode() colour.Code.Should().Be(code); } - [Test] + [Fact] public void ToStringReturnsCode() { var colour = Colour.White; @@ -27,7 +23,7 @@ public void ToStringReturnsCode() colour.ToString().Should().Be(colour.Code); } - [Test] + [Fact] public void ShouldPerformImplicitConversionToColourCodeString() { string code = Colour.White; @@ -35,7 +31,7 @@ public void ShouldPerformImplicitConversionToColourCodeString() code.Should().Be("#FFFFFF"); } - [Test] + [Fact] public void ShouldPerformExplicitConversionGivenSupportedColourCode() { var colour = (Colour)"#FFFFFF"; @@ -43,7 +39,7 @@ public void ShouldPerformExplicitConversionGivenSupportedColourCode() colour.Should().Be(Colour.White); } - [Test] + [Fact] public void ShouldThrowUnsupportedColourExceptionGivenNotSupportedColourCode() { FluentActions.Invoking(() => Colour.From("##FF33CC"))