From c91e16be93c10f998d7051f7484eef166d42d711 Mon Sep 17 00:00:00 2001
From: Matej Vavrek <matvav13@gmail.com>
Date: Tue, 12 Nov 2024 01:32:11 +0100
Subject: [PATCH] Created tests for RestaurantService, fixed a few mistakes

---
 Api/Controllers/RestaurantController.cs       |   4 +-
 .../BusinessLayer.Tests.csproj                |   1 +
 .../Services/RestaurantServiceTests.cs        | 296 ++++++++++++++++++
 .../DTOs/Restaurant/RestaurantDetailDto.cs    |  29 +-
 .../ReviewAggregate/ReviewAggregateDTO.cs     |   5 +-
 .../RestaurantService/IRestaurantService.cs   |   7 +-
 .../RestaurantService/RestaurantService.cs    |  17 +-
 DAL/Data/RestaurantDBContext.cs               |  18 +-
 TestUtilities/FakeData/FakeDataInitializer.cs |   5 +-
 TestUtilities/Mocks/MockedDbContext.cs        |   2 +-
 TestUtilities/TestUtilities.csproj            |   2 +-
 pv179-project.sln                             |  12 +-
 12 files changed, 351 insertions(+), 47 deletions(-)
 create mode 100644 BusinessLayer.Tests/Services/RestaurantServiceTests.cs

diff --git a/Api/Controllers/RestaurantController.cs b/Api/Controllers/RestaurantController.cs
index 2c3923e..a2295cf 100644
--- a/Api/Controllers/RestaurantController.cs
+++ b/Api/Controllers/RestaurantController.cs
@@ -59,8 +59,8 @@ namespace Api.Controllers
             [FromBody] RestaurantUpdateDto data)
         {
             if (data.Name is null && data.About is null
-                                  && data.Email is null && data.Web is null
-                                  && data.Phone is null && data.Category is null)
+                && data.Email is null && data.Web is null
+                && data.Phone is null && data.Category is null)
             {
                 return BadRequest("No data was provided.");
             }
diff --git a/BusinessLayer.Tests/BusinessLayer.Tests.csproj b/BusinessLayer.Tests/BusinessLayer.Tests.csproj
index 71f2579..eb0347e 100644
--- a/BusinessLayer.Tests/BusinessLayer.Tests.csproj
+++ b/BusinessLayer.Tests/BusinessLayer.Tests.csproj
@@ -19,6 +19,7 @@
 
   <ItemGroup>
     <ProjectReference Include="..\BusinessLayer\BusinessLayer.csproj" />
+    <ProjectReference Include="..\TestUtilities\TestUtilities.csproj" />
   </ItemGroup>
 
   <ItemGroup>
diff --git a/BusinessLayer.Tests/Services/RestaurantServiceTests.cs b/BusinessLayer.Tests/Services/RestaurantServiceTests.cs
new file mode 100644
index 0000000..2fd9086
--- /dev/null
+++ b/BusinessLayer.Tests/Services/RestaurantServiceTests.cs
@@ -0,0 +1,296 @@
+using BusinessLayer.DTOs.Location;
+using BusinessLayer.DTOs.Restaurant;
+using BusinessLayer.Services.RestaurantService;
+using BusinessLayer.Utils.Filters;
+using BusinessLayer.Utils.Ordering;
+using DAL.Constants;
+using DAL.Data;
+using Microsoft.EntityFrameworkCore;
+using TestUtilities.Mocks;
+
+namespace BusinessLayer.Tests.Services
+{
+    public class RestaurantServiceTests
+    {
+        private DbContextOptions<RestaurantDBContext> _dbContextOptions;
+        private RestaurantDBContext _dbContext;
+        private RestaurantService _service;
+
+        public RestaurantServiceTests()
+        {
+            _dbContextOptions = MockedDbContext.CreateInMemoryContextOptions();
+            _dbContext = MockedDbContext.CreateContext(_dbContextOptions);
+            _service = new RestaurantService(_dbContext);
+        }
+
+        [Fact]
+        public async Task GetRestaurants_IdMatch()
+        {
+            // Arrange
+            var ids = new Guid[] { SeedingValues.Restaurant1Id, SeedingValues.Restaurant2Id };
+
+            // Act
+            var result = await _service.GetRestaurantsAsync(new RestaurantFilter(), RestaurantOrdering.CreatedAtDesc, 0, 0, ids);
+
+            // Assert
+            Assert.Equal(ids.Length, result.Count);
+            Assert.All(ids, id => Assert.Contains(result, r => r.Id == id));
+        }
+
+        [Fact]
+        public async Task GetRestaurants_IdMatchNotExists_EmptyList()
+        {
+            // Arrange
+            var ids = new Guid[] { Guid.NewGuid() };
+
+            // Act
+            var result = await _service.GetRestaurantsAsync(new RestaurantFilter(), RestaurantOrdering.CreatedAtDesc, 0, 0, ids);
+
+            // Assert
+            Assert.Empty(result);
+        }
+
+        [Theory]
+        [InlineData(RestaurantOrdering.Name)]
+        [InlineData(RestaurantOrdering.NameDesc)]
+        [InlineData(RestaurantOrdering.CreatedAtDesc)]
+        public async Task GetRestaurants_OrderByName(RestaurantOrdering ordering)
+        {
+            // Arrange
+            // Whoops, nothing to arrange here! ¯\_(ツ)_/¯
+
+            // Act
+            var result = await _service.GetRestaurantsAsync(new RestaurantFilter(), ordering);
+
+            // Assert
+            Assert.NotEmpty(result);
+            var first = result.First();
+            foreach (var second in result.Skip(1))
+            {
+                CheckOrdering(ordering, first, second);
+            }
+        }
+
+        private static void CheckOrdering(RestaurantOrdering ordering, RestaurantDto first, RestaurantDto second)
+        {
+            switch (ordering)
+            {
+                case RestaurantOrdering.Name:
+                    Assert.True(first.Name.CompareTo(second.Name) <= 0);
+                    return;
+                case RestaurantOrdering.NameDesc:
+                    Assert.True(first.Name.CompareTo(second.Name) >= 0);
+                    return;
+                case RestaurantOrdering.CreatedAtDesc:
+                    Assert.True(first.CreatedAt >= second.CreatedAt);
+                    return;
+            }
+        }
+
+        [Fact]
+        public async Task GetRestaurants_CategoryFiltering()
+        {
+            // Arrange
+            string expectedCategoryPart = "izza";
+            RestaurantFilter ordering = new()
+            {
+                CategoryLike = expectedCategoryPart,
+            };
+
+            // Act
+            var result = await _service.GetRestaurantsAsync(ordering, RestaurantOrdering.CreatedAtDesc);
+
+            // Assert
+            Assert.NotEmpty(result);
+            Assert.Single(result);
+            Assert.All(result, r => r.Category.Contains(expectedCategoryPart));
+        }
+
+        [Fact]
+        public async Task GetRestaurants_NameFiltering()
+        {
+            // Arrange
+            string expectedNamePart = "Doe";
+            RestaurantFilter ordering = new()
+            {
+                NameLike = expectedNamePart,
+            };
+
+            // Act
+            var result = await _service.GetRestaurantsAsync(ordering, RestaurantOrdering.CreatedAtDesc);
+
+            // Assert
+            Assert.NotEmpty(result);
+            Assert.Single(result);
+            Assert.All(result, r => r.Name.Contains(expectedNamePart));
+        }
+
+        [Fact]
+        public async Task GetRestaurant_Exists()
+        {
+            // Arrange
+            Guid expectedId = SeedingValues.Restaurant1Id;
+            
+            // Act
+            var result = await _service.GetRestaurantAsync(expectedId);
+
+            // Assert
+            Assert.NotNull(result);
+            Assert.Equal(expectedId, result.Id);
+            Assert.Null(result.DeletedAt);
+        }
+
+        [Fact]
+        public async Task GetRestaurant_NotExists()
+        {
+            // Arrange
+            Guid notExistsId = Guid.NewGuid();
+
+            // Act
+            var result = await _service.GetRestaurantAsync(notExistsId);
+
+            // Assert
+            Assert.Null(result);
+        }
+
+        [Fact]
+        public async Task CreateRestaurant_Valid_Succeeds()
+        {
+            // Arrange
+            var mainterId = SeedingValues.User1Id;
+            const string name = "OloMocTvaruzku";
+            const string about = "Come eat your heart out in our all you can eat menu composed mostly of variants of olomoucke tvaruzky.";
+            const string category = "CHEESE!!!!!";
+
+            var location = new LocationCreateDto()
+            {
+                Country = "Czech Republic",
+                City = "Brno",
+                Address = "Holandska 68a",
+                Zipcode = "60200"
+            };
+
+            var data = new RestaurantCreateDto()
+            {
+                MaintainerId = mainterId,
+                Name = name,
+                About = about,
+                Category = category,
+                Location = location
+            };
+
+            // Act
+            var result = await _service.CreateRestaurantAsync(data);
+
+            // Assert
+            Assert.NotNull(result);
+            Assert.Equal(name, result.Name);
+            Assert.Equal(about, result.About);
+            Assert.Equal(category, result.Category);
+            Assert.Null(result.DeletedAt);
+        }
+
+        [Fact]
+        public async Task CreateRestaurant_MaintainerNotExists_Fails()
+        {
+            // Arrange
+            var mainterId = SeedingValues.User1Id;
+            const string name = "OloMocTvaruzku";
+            const string about = "Come eat your heart out in our all you can eat menu composed mostly of variants of olomoucke tvaruzky.";
+            const string category = "CHEESE!!!!!";
+
+            var location = new LocationCreateDto()
+            {
+                Country = "Czech Republic",
+                City = "Brno",
+                Address = "Holandska 68a",
+                Zipcode = "60200"
+            };
+
+            var data = new RestaurantCreateDto()
+            {
+                MaintainerId = mainterId,
+                Name = name,
+                About = about,
+                Category = category,
+                Location = location
+            };
+
+            // Act
+            var result = await _service.CreateRestaurantAsync(data);
+
+            // Assert
+            Assert.NotNull(result);
+            Assert.Equal(name, result.Name);
+            Assert.Equal(about, result.About);
+            Assert.Equal(category, result.Category);
+            Assert.Null(result.DeletedAt);
+        }
+
+        [Fact]
+        public async Task UpdateRestaurant_Valid_Succeeds()
+        {
+            // Arrange
+            string name = "MyRestaurant.exe";
+            var restaurantData = new RestaurantUpdateDto
+            {
+                Name = name
+            };
+
+            var restaurantId = SeedingValues.Restaurant1Id;
+
+            // Act
+            var result = await _service.UpdateRestaurantAsync(restaurantId, restaurantData);
+
+            // Assert
+            Assert.NotNull(result);
+            Assert.Equal(name, result.Name);
+            Assert.NotEqual(result.CreatedAt, result.UpdatedAt);
+        }
+
+        [Fact]
+        public async Task UpdateRestaurant_NotExists_Fails()
+        {
+            // Arrange
+            string name = "MyRestaurant.exe";
+            var restaurantData = new RestaurantUpdateDto
+            {
+                Name = name
+            };
+
+            var restaurantId = Guid.NewGuid();
+
+            // Act
+            var result = await _service.UpdateRestaurantAsync(restaurantId, restaurantData);
+
+            // Assert
+            Assert.Null(result);
+        }
+
+        [Fact]
+        public async Task DeleteRestaurant_Exists_Succeeds()
+        {
+            // Arrange
+            var restaurantId = SeedingValues.Restaurant1Id;
+
+            // Act
+            var result = await _service.DeleteRestaurantAsync(restaurantId, true);
+
+            // Assert
+            Assert.True(result);
+        }
+
+        [Fact]
+        public async Task DeletedRestaurant_NotExists_Fails()
+        {
+            // Arrange
+            var restaurantId = Guid.NewGuid();
+
+            // Act
+            var result = await _service.DeleteRestaurantAsync(restaurantId, true);
+
+            // Assert
+            Assert.False(result);
+        }
+    }
+}
diff --git a/BusinessLayer/DTOs/Restaurant/RestaurantDetailDto.cs b/BusinessLayer/DTOs/Restaurant/RestaurantDetailDto.cs
index 3e7f153..c4220b2 100644
--- a/BusinessLayer/DTOs/Restaurant/RestaurantDetailDto.cs
+++ b/BusinessLayer/DTOs/Restaurant/RestaurantDetailDto.cs
@@ -6,21 +6,18 @@ namespace BusinessLayer.DTOs.Restaurant
 {
     public record RestaurantDetailDto
     {
-        public record RestaurantDto
-        {
-            public Guid Id { get; set; }
-            public required LocationDto Location { get; set; }
-            public ReviewAggregateDTO? ReviewAggregate { get; set; }
-            public required List<UserDto> RestaurantMaintainers { get; set; }
-            public required string Name { get; set; }
-            public string? About { get; set; }
-            public string? Phone { get; set; }
-            public string? Email { get; set; }
-            public string? Web { get; set; }
-            public required string Category { get; set; }
-            public DateTime CreatedAt { get; set; }
-            public DateTime UpdatedAt { get; set; }
-            public DateTime? DeletedAt { get; set; }
-        }
+        public Guid Id { get; set; }
+        public required LocationDto Location { get; set; }
+        public ReviewAggregateDTO? ReviewAggregate { get; set; }
+        public required List<UserDto> RestaurantMaintainers { get; set; }
+        public required string Name { get; set; }
+        public string? About { get; set; }
+        public string? Phone { get; set; }
+        public string? Email { get; set; }
+        public string? Web { get; set; }
+        public required string Category { get; set; }
+        public DateTime CreatedAt { get; set; }
+        public DateTime UpdatedAt { get; set; }
+        public DateTime? DeletedAt { get; set; }
     }
 }
\ No newline at end of file
diff --git a/BusinessLayer/DTOs/ReviewAggregate/ReviewAggregateDTO.cs b/BusinessLayer/DTOs/ReviewAggregate/ReviewAggregateDTO.cs
index 20f7c25..b6261b5 100644
--- a/BusinessLayer/DTOs/ReviewAggregate/ReviewAggregateDTO.cs
+++ b/BusinessLayer/DTOs/ReviewAggregate/ReviewAggregateDTO.cs
@@ -1,11 +1,8 @@
-using BusinessLayer.DTOs.Restaurant;
-
-namespace BusinessLayer.DTOs.ReviewAggregate
+namespace BusinessLayer.DTOs.ReviewAggregate
 {
     public class ReviewAggregateDTO
     {
         public Guid RestaurantId { get; set; }
-        public RestaurantDto? Restaurant { get; set; }
         public uint FoodRating { get; set; }
         public uint ServiceRating { get; set; }
         public uint EnvironmentRating { get; set; }
diff --git a/BusinessLayer/Services/RestaurantService/IRestaurantService.cs b/BusinessLayer/Services/RestaurantService/IRestaurantService.cs
index 5c356b7..c37174c 100644
--- a/BusinessLayer/Services/RestaurantService/IRestaurantService.cs
+++ b/BusinessLayer/Services/RestaurantService/IRestaurantService.cs
@@ -13,10 +13,13 @@ namespace BusinessLayer.Services.RestaurantService
             int offset = 0,
             Guid[]? ids = null);
         public Task<RestaurantDetailDto?> GetRestaurantAsync(Guid id);
-        public Task<RestaurantDetailDto?> CreateRestaurantAsync(RestaurantCreateDto restaurant);
+        public Task<RestaurantDetailDto?> CreateRestaurantAsync(
+            RestaurantCreateDto restaurant,
+            bool save = true);
         public Task<RestaurantDetailDto?> UpdateRestaurantAsync(
             Guid id,
-            RestaurantUpdateDto restaurant);
+            RestaurantUpdateDto restaurant,
+            bool save = true);
         public Task<bool> DeleteRestaurantAsync(
             Guid id,
             bool save = true);
diff --git a/BusinessLayer/Services/RestaurantService/RestaurantService.cs b/BusinessLayer/Services/RestaurantService/RestaurantService.cs
index dc68e93..ecc65c3 100644
--- a/BusinessLayer/Services/RestaurantService/RestaurantService.cs
+++ b/BusinessLayer/Services/RestaurantService/RestaurantService.cs
@@ -23,9 +23,10 @@ namespace BusinessLayer.Services.RestaurantService
             return await _dbContext.Restaurants
                 .Include(r => r.ReviewAggregate)
                 .Where(filter.ComposeFilterFunc(ids))
-                .ApplyPagination(limit, offset)
                 .ApplyOrdering(orderBy)
-                .Select(r => r.Adapt<RestaurantDto>()).ToListAsync();
+                .ApplyPagination(limit, offset)
+                .Select(r => r.Adapt<RestaurantDto>())
+                .ToListAsync();
         }
 
         public async Task<RestaurantDetailDto?> GetRestaurantAsync(Guid id)
@@ -45,7 +46,8 @@ namespace BusinessLayer.Services.RestaurantService
             return restaurant.Adapt<RestaurantDetailDto>();
         }
 
-        public async Task<RestaurantDetailDto?> CreateRestaurantAsync(RestaurantCreateDto data)
+        public async Task<RestaurantDetailDto?> CreateRestaurantAsync(
+            RestaurantCreateDto data, bool save = true)
         {
             var maintainer = await _dbContext.Users.FindAsync(data.MaintainerId);
             
@@ -78,12 +80,13 @@ namespace BusinessLayer.Services.RestaurantService
             
             await _dbContext.Restaurants.AddAsync(restaurant);
             maintainer.MaintainedRestaurants.Add(restaurant);
-            await _dbContext.SaveChangesAsync();
+            await SaveAsync(save);
 
             return restaurant.Adapt<RestaurantDetailDto>();
         }
 
-        public async Task<RestaurantDetailDto?> UpdateRestaurantAsync(Guid id, RestaurantUpdateDto data)
+        public async Task<RestaurantDetailDto?> UpdateRestaurantAsync(
+            Guid id, RestaurantUpdateDto data, bool save = true)
         {
             var restaurant = await _dbContext.Restaurants.FindAsync(id);
 
@@ -101,7 +104,7 @@ namespace BusinessLayer.Services.RestaurantService
             restaurant.UpdatedAt = DateTime.UtcNow;
 
             _dbContext.Restaurants.Update(restaurant);
-            await _dbContext.SaveChangesAsync();
+            await SaveAsync(save);
             return restaurant.Adapt<RestaurantDetailDto>();
         }
 
@@ -131,7 +134,7 @@ namespace BusinessLayer.Services.RestaurantService
 
             _dbContext.Restaurants.Update(restaurant);
             _dbContext.Locations.Update(location);
-            await _dbContext.SaveChangesAsync(save);
+            await SaveAsync(save);
 
             return true;
         }
diff --git a/DAL/Data/RestaurantDBContext.cs b/DAL/Data/RestaurantDBContext.cs
index 1b380f3..520a700 100644
--- a/DAL/Data/RestaurantDBContext.cs
+++ b/DAL/Data/RestaurantDBContext.cs
@@ -5,17 +5,17 @@ namespace DAL.Data
 {
     public class RestaurantDBContext : DbContext
     {
-        public DbSet<User> Users { get; set; }
-        public DbSet<Review> Reviews { get; set; }
-        public DbSet<ReviewComment> ReviewComments { get; set; }
-        public DbSet<ReviewAggregateResult> ReviewAggregateResults { get; set; }
-        public DbSet<Event> Events { get; set; }
-        public DbSet<EventComment> EventComments { get; set; }
-        public DbSet<EventParticipant> EventParticipants { get; set; }
+        public virtual DbSet<User> Users { get; set; }
+        public virtual DbSet<Review> Reviews { get; set; }
+        public virtual DbSet<ReviewComment> ReviewComments { get; set; }
+        public virtual DbSet<ReviewAggregateResult> ReviewAggregateResults { get; set; }
+        public virtual DbSet<Event> Events { get; set; }
+        public virtual DbSet<EventComment> EventComments { get; set; }
+        public virtual DbSet<EventParticipant> EventParticipants { get; set; }
 
-        public DbSet<Restaurant> Restaurants { get; set; }
+        public virtual DbSet<Restaurant> Restaurants { get; set; }
 
-        public DbSet<Location> Locations { get; set; }
+        public virtual DbSet<Location> Locations { get; set; }
 
         public RestaurantDBContext(DbContextOptions<RestaurantDBContext> options) : base(options) { }
 
diff --git a/TestUtilities/FakeData/FakeDataInitializer.cs b/TestUtilities/FakeData/FakeDataInitializer.cs
index 201bca8..7c05718 100644
--- a/TestUtilities/FakeData/FakeDataInitializer.cs
+++ b/TestUtilities/FakeData/FakeDataInitializer.cs
@@ -21,7 +21,7 @@ namespace TestUtilities.FakeData
 
             var reviewAggregates = reviews
                 .GroupBy(r => r.RestaurantId)
-                .Select(group => new ReviewAggregate
+                .Select(group => new ReviewAggregateResult
                 {
                     RestaurantId = group.Key,
                     FoodRating = (uint)Math.Round(group.Average(item => item.FoodRating)),
@@ -29,7 +29,8 @@ namespace TestUtilities.FakeData
                     EnvironmentRating = (uint)Math.Round(group.Average(item => item.EnvironmentRating))
                 });
 
-            context.ReviewAggregate.AddRange(reviewAggregates);
+            context.ReviewAggregateResults.AddRange(reviewAggregates);
+            context.SaveChanges();
         }
         private static List<User> PrepareUserModels()
         {
diff --git a/TestUtilities/Mocks/MockedDbContext.cs b/TestUtilities/Mocks/MockedDbContext.cs
index 56ddac6..14bc67c 100644
--- a/TestUtilities/Mocks/MockedDbContext.cs
+++ b/TestUtilities/Mocks/MockedDbContext.cs
@@ -11,7 +11,7 @@ namespace TestUtilities.Mocks
         public static DbContextOptions<RestaurantDBContext> CreateInMemoryContextOptions()
         {
             return new DbContextOptionsBuilder<RestaurantDBContext>()
-                .UseInMemoryDatabase(DBName).Options;
+                .UseInMemoryDatabase(Guid.NewGuid().ToString()).Options;
         }
 
         public static RestaurantDBContext CreateContext(DbContextOptions<RestaurantDBContext> options)
diff --git a/TestUtilities/TestUtilities.csproj b/TestUtilities/TestUtilities.csproj
index d672305..947d4fb 100644
--- a/TestUtilities/TestUtilities.csproj
+++ b/TestUtilities/TestUtilities.csproj
@@ -7,8 +7,8 @@
   </PropertyGroup>
 
   <ItemGroup>
+    <PackageReference Include="EntityFrameworkCore.Testing.NSubstitute" Version="8.0.0" />
     <PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="8.0.10" />
-    <PackageReference Include="NSubstitute" Version="5.3.0" />
   </ItemGroup>
 
   <ItemGroup>
diff --git a/pv179-project.sln b/pv179-project.sln
index 6475a2f..fb9b03f 100644
--- a/pv179-project.sln
+++ b/pv179-project.sln
@@ -7,11 +7,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Api", "Api\Api.csproj", "{3
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DAL", "DAL\DAL.csproj", "{5BA37FEF-E2CC-43A8-8D69-FD40FB2B9454}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BusinessLayer", "BusinessLayer\BusinessLayer.csproj", "{539D3A8E-5CD3-4236-81B0-C36537BC6B68}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BusinessLayer", "BusinessLayer\BusinessLayer.csproj", "{539D3A8E-5CD3-4236-81B0-C36537BC6B68}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MVC", "MVC\MVC.csproj", "{11AD9763-446E-4FD8-AC2D-BF092CAE16DE}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MVC", "MVC\MVC.csproj", "{11AD9763-446E-4FD8-AC2D-BF092CAE16DE}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BusinessLayer.Tests", "BusinessLayer.Tests\BusinessLayer.Tests.csproj", "{B244DC7E-77CF-4B9A-B382-BC8E1E4B057C}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BusinessLayer.Tests", "BusinessLayer.Tests\BusinessLayer.Tests.csproj", "{B244DC7E-77CF-4B9A-B382-BC8E1E4B057C}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestUtilities", "TestUtilities\TestUtilities.csproj", "{7F02D143-33B1-4A83-BE5E-8AE192DA6A8D}"
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -39,6 +41,10 @@ Global
 		{B244DC7E-77CF-4B9A-B382-BC8E1E4B057C}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{B244DC7E-77CF-4B9A-B382-BC8E1E4B057C}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{B244DC7E-77CF-4B9A-B382-BC8E1E4B057C}.Release|Any CPU.Build.0 = Release|Any CPU
+		{7F02D143-33B1-4A83-BE5E-8AE192DA6A8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{7F02D143-33B1-4A83-BE5E-8AE192DA6A8D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{7F02D143-33B1-4A83-BE5E-8AE192DA6A8D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{7F02D143-33B1-4A83-BE5E-8AE192DA6A8D}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
-- 
GitLab