diff --git a/TestUtilities/FakeData/FakeDataInitializer.cs b/TestUtilities/FakeData/FakeDataInitializer.cs new file mode 100644 index 0000000000000000000000000000000000000000..201bca8407a7911e1553c7d446c10b473b65faf9 --- /dev/null +++ b/TestUtilities/FakeData/FakeDataInitializer.cs @@ -0,0 +1,305 @@ +using DAL.Constants; +using DAL.Models; +using DAL.Enums; +using DAL.Data; + +namespace TestUtilities.FakeData +{ + internal class FakeDataInitializer + { + public static void PrepareData(RestaurantDBContext context) + { + var reviews = PrepareReviewModels(); + context.Users.AddRange(PrepareUserModels()); + context.Reviews.AddRange(reviews); + context.ReviewComments.AddRange(PrepareReviewCommentsModels()); + context.Events.AddRange(PrepareEventModels()); + context.EventParticipants.AddRange(PrepareEventParticipantModels()); + context.EventComments.AddRange(PrepareEventCommentModels()); + context.Restaurants.AddRange(PrepareRestaurantModels()); + context.Locations.AddRange(PrepareLocationModels()); + + var reviewAggregates = reviews + .GroupBy(r => r.RestaurantId) + .Select(group => new ReviewAggregate + { + RestaurantId = group.Key, + FoodRating = (uint)Math.Round(group.Average(item => item.FoodRating)), + ServiceRating = (uint)Math.Round(group.Average(item => item.ServiceRating)), + EnvironmentRating = (uint)Math.Round(group.Average(item => item.EnvironmentRating)) + }); + + context.ReviewAggregate.AddRange(reviewAggregates); + } + private static List<User> PrepareUserModels() + { + return + [ + new User + { + Id = SeedingValues.User1Id, + Name = "Vit23", + Email = "Vit23@gmail.com", + CreatedAt = new DateTime(2024, 10, 01, 08, 20, 05), + UpdatedAt = new DateTime(2024, 10, 01, 08, 20, 05) + }, + new User + { + Id = SeedingValues.User2Id, + Name = "Erik512", + Email = "Erikuss.Cool@gmail.com", + CreatedAt = new DateTime(2024, 10, 01, 04, 20, 00), + UpdatedAt = new DateTime(2024, 10, 01, 04, 20, 00) + }, + new User + { + Id = SeedingValues.User3Id, + Name = "Jakub23423", + Email = "Jaqub@azet.sk", + CreatedAt = new DateTime(2024, 10, 05, 14, 23, 21), + UpdatedAt = new DateTime(2024, 10, 05, 14, 23, 21) + } + ]; + } + + private static List<Review> PrepareReviewModels() + { + return + [ + new Review + { + Id = SeedingValues.Review1Id, + PosterId = SeedingValues.User1Id, + RestaurantId = SeedingValues.Restaurant1Id, + Content = "The food was pretty good, but there were a lot of people and I could barely hear my friend. Due to this, the service was quite busy and it took them a while to get me food.", + FoodRating = 8, + EnvironmentRating = 3, + ServiceRating = 1, + TimeSpent = 65.07f, + LeftTip = false, + CreatedAt = new DateTime(2024, 10, 04, 23, 39, 1), + UpdatedAt = new DateTime(2024, 10, 04, 23, 39, 1) + }, + new Review + { + Id = SeedingValues.Review2Id, + PosterId = SeedingValues.User3Id, + RestaurantId = SeedingValues.Restaurant1Id, + Content = "Good restaurant, very enjoy. Environment not so good - toilet door stuck. Send help.", + FoodRating = 10, + EnvironmentRating = 1, + ServiceRating = 9, + TimeSpent = 3.0f, + LeftTip = false, + ServesFreeWater = true, + CreatedAt = new DateTime(2024, 10, 05, 20, 5, 16), + UpdatedAt = new DateTime(2024, 10, 05, 20, 5, 16) + }, + new Review + { + Id = SeedingValues.Review3Id, + PosterId = SeedingValues.User3Id, + RestaurantId = SeedingValues.Restaurant2Id, + Content = "The pizza is great, burned my tongue with how excited I was to eat. Service was decent. The environment was amazing, too!", + FoodRating = 10, + EnvironmentRating = 8, + ServiceRating = 8, + TimeSpent = 2.5f, + LeftTip = true, + CreatedAt = new DateTime(2024, 10, 10, 16, 41, 2), + UpdatedAt = new DateTime(2024, 10, 10, 16, 41, 2) + } + ]; + } + + private static List<ReviewComment> PrepareReviewCommentsModels() + { + return + [ + new ReviewComment + { + Id = SeedingValues.ReviewComment1Id, + PosterId = SeedingValues.User2Id, + ReviewId = SeedingValues.Review1Id, + Content = "Hello, I am the owner of this restaurant. I don't think it is right for you to rate us badly because we get a lot of customers.", + CreatedAt = new DateTime(2024, 10, 05, 23, 14, 5), + UpdatedAt = new DateTime(2024, 10, 05, 23, 14, 5) + }, + new ReviewComment + { + Id = SeedingValues.ReviewComment2Id, + PosterId = SeedingValues.User1Id, + ReviewId = SeedingValues.Review1Id, + ParentCommentId = SeedingValues.ReviewComment1Id, + Content = "OK.", + CreatedAt = new DateTime(2024, 10, 06, 23, 18, 1), + UpdatedAt = new DateTime(2024, 10, 06, 23, 18, 1) + }, + new ReviewComment + { + Id = SeedingValues.ReviewComment3Id, + PosterId = SeedingValues.User2Id, + ReviewId = SeedingValues.Review2Id, + Content = "Oh my god! Are you still in there?!", + CreatedAt = new DateTime(2024, 10, 06, 10, 5, 6), + UpdatedAt = new DateTime(2024, 10, 06, 10, 5, 6) + }, + new ReviewComment + { + Id = SeedingValues.ReviewComment4Id, + PosterId = SeedingValues.User3Id, + ReviewId = SeedingValues.Review2Id, + ParentCommentId = SeedingValues.ReviewComment3Id, + Content = "No, no, it's all good now. Turns out I just locked it.", + CreatedAt = new DateTime(2024, 10, 06, 11, 3, 0), + UpdatedAt = new DateTime(2024, 10, 06, 11, 3, 0), + + } + ]; + } + + private static List<Event> PrepareEventModels() + { + return new List<Event> + { + new Event + { + Id = SeedingValues.Event1Id, + Title = "Exclusive Dinner Event", + RestaurantId = SeedingValues.Restaurant1Id, + Date = new DateTime(2024, 10, 30, 12, 20, 23), + Content = "Join us for an exclusive dinner with gourmet cuisine.", + CreatedAt = new DateTime(2024, 10, 20, 12, 20, 23), + UpdatedAt = new DateTime(2024, 10, 20, 12, 20, 23) + }, + new Event + { + Id = SeedingValues.Event2Id, + Title = "Wine Tasting Evening", + RestaurantId = SeedingValues.Restaurant1Id, + Date = new DateTime(2024, 10, 27, 10, 23, 23), + Content = "An evening of exquisite wine tasting with fine cheeses.", + CreatedAt = new DateTime(2024, 10, 12, 10, 23, 23), + UpdatedAt = new DateTime(2024, 10, 12, 10, 23, 23), + } + }; + } + + private static List<EventParticipant> PrepareEventParticipantModels() + { + return new List<EventParticipant> + { + new EventParticipant + { + UserId = SeedingValues.User3Id, + EventId = SeedingValues.Event1Id, + Attendance = ParticipantType.Creator, + CreatedAt = new DateTime(2024, 10, 20, 12, 20, 23), + UpdatedAt = new DateTime(2024, 10, 20, 12, 20, 23) + }, + new EventParticipant + { + UserId = SeedingValues.User1Id, + EventId = SeedingValues.Event1Id, + Attendance = ParticipantType.Attending, + CreatedAt = new DateTime(2024, 10, 21, 10, 23, 23), + UpdatedAt = new DateTime(2024, 10, 21, 10, 23, 23) + }, + new EventParticipant + { + UserId = SeedingValues.User2Id, + EventId = SeedingValues.Event1Id, + Attendance = ParticipantType.Tentative, + CreatedAt = new DateTime(2024, 10, 20, 15, 20, 23), + UpdatedAt = new DateTime(2024, 10, 20, 15, 20, 23) + }, + new EventParticipant + { + UserId = SeedingValues.User1Id, + EventId = SeedingValues.Event2Id, + Attendance = ParticipantType.Attending, + CreatedAt = new DateTime(2024, 10, 12, 10, 23, 23), + UpdatedAt = new DateTime(2024, 10, 12, 10, 23, 23) + }, + }; + } + + private static List<EventComment> PrepareEventCommentModels() + { + return new List<EventComment> + { + new EventComment + { + Id = SeedingValues.EventComment1Id, + PosterId = SeedingValues.User2Id, + EventId = SeedingValues.Event1Id, + Content = "Looking forward to this event!", + CreatedAt = new DateTime(2024, 10, 21, 18, 23, 23), + UpdatedAt = new DateTime(2024, 10, 21, 18, 23, 23) + }, + new EventComment + { + Id = SeedingValues.EventComment2Id, + PosterId = SeedingValues.User1Id, + EventId = SeedingValues.Event1Id, + ParentCommentId = SeedingValues.EventComment1Id, + Content = "Me too! It sounds like a great night.", + CreatedAt = new DateTime(2024, 10, 21, 19, 26, 23), + UpdatedAt = new DateTime(2024, 10, 21, 19, 26, 23) + } + }; + } + + private static List<Restaurant> PrepareRestaurantModels() => + [ + new Restaurant + { + Id = SeedingValues.Restaurant1Id, + Name = "U DĹ™eváka Beer&Grill", + Category = "pub", + About = "V tomhle jednoduchĂ©m, ale ĂştulnĂ©m podniku se zahrádkou je k dostánĂ poctivĂ© jĂdlo i pivo nÄ›kolika pivovarĹŻ.", + Email = "info@udrevaka.cz", + Phone = "724 000 723", + Web = "https://udrevaka.cz/", + CreatedAt = new DateTime(2024, 10, 01, 6, 7, 23), + UpdatedAt = new DateTime(2024, 10, 01, 6, 7, 23) + }, + new Restaurant + { + Id = SeedingValues.Restaurant2Id, + Name = "Doe Boy Brno", + Category = "pizza", + About = "Authentic Neapolitan Pizza // The taste of Naples in Brno", + Email = "", + Phone = "773 993 222", + Web = "https://facebook.com/pages/category/Pizza-Place/Doe-Boy-Brno-101177877951369/", + CreatedAt = new DateTime(2024, 10, 01, 12, 1, 0), + UpdatedAt = new DateTime(2024, 10, 01, 12, 1, 0), + } + ]; + + private static List<Location> PrepareLocationModels() => + [ + new Location + { + RestaurantId = SeedingValues.Restaurant1Id, + Country = "Czech Republic", + City = "Brno", + Address = "DĹ™evaĹ™ská 806/22", + Zipcode = "60200", + CreatedAt = new DateTime(2024, 10, 01, 6, 7, 23), + UpdatedAt = new DateTime(2024, 10, 01, 6, 7, 23) + }, + new Location + { + RestaurantId = SeedingValues.Restaurant2Id, + Country = "Czech Republic", + City = "Brno", + Address = "Ĺ tefánikova 39", + Zipcode = "60200", + CreatedAt = new DateTime(2024, 10, 01, 12, 1, 0), + UpdatedAt = new DateTime(2024, 10, 01, 12, 1, 0) + } + ]; + } +} diff --git a/TestUtilities/Mocks/MockedDbContext.cs b/TestUtilities/Mocks/MockedDbContext.cs new file mode 100644 index 0000000000000000000000000000000000000000..56ddac6b3b4459ed0a69ce922be0267eff1505ad --- /dev/null +++ b/TestUtilities/Mocks/MockedDbContext.cs @@ -0,0 +1,31 @@ +using DAL.Data; +using EntityFrameworkCore.Testing.NSubstitute.Helpers; +using TestUtilities.FakeData; + +namespace TestUtilities.Mocks +{ + public class MockedDbContext + { + public static string DBName = Guid.NewGuid().ToString(); + + public static DbContextOptions<RestaurantDBContext> CreateInMemoryContextOptions() + { + return new DbContextOptionsBuilder<RestaurantDBContext>() + .UseInMemoryDatabase(DBName).Options; + } + + public static RestaurantDBContext CreateContext(DbContextOptions<RestaurantDBContext> options) + { + var dbContextMock = new RestaurantDBContext(options); + + var dbContext = new MockedDbContextBuilder<RestaurantDBContext>() + .UseDbContext(dbContextMock) + .UseConstructorWithParameters(options) + .MockedDbContext; + + FakeDataInitializer.PrepareData(dbContext); + + return dbContext; + } + } +} diff --git a/TestUtilities/Mocks/MockedDependencyInjectionBuilder.cs b/TestUtilities/Mocks/MockedDependencyInjectionBuilder.cs new file mode 100644 index 0000000000000000000000000000000000000000..1c7c0248782a8a3242a8a2a36521e09dcc7469f8 --- /dev/null +++ b/TestUtilities/Mocks/MockedDependencyInjectionBuilder.cs @@ -0,0 +1,49 @@ +using DAL.Data; +using Microsoft.Extensions.DependencyInjection; + +namespace TestUtilities.Mocks +{ + public class MockedDependencyInjectionBuilder + { + protected IServiceCollection _serviceCollection = new ServiceCollection(); + + public MockedDependencyInjectionBuilder() { } + + public MockedDependencyInjectionBuilder AddMockDBContext() + { + _serviceCollection = _serviceCollection + .AddDbContext<RestaurantDBContext>( + options => options.UseInMemoryDatabase(MockedDbContext.DBName)); + + return this; + } + + public MockedDependencyInjectionBuilder AddScoped<T>(T obj) where T : class + { + _serviceCollection = _serviceCollection.AddScoped<T>(_ => obj); + + return this; + } + + public ServiceProvider Create() + { + return _serviceCollection.BuildServiceProvider(); + } + + public MockedDependencyInjectionBuilder AddServices() + { + //_serviceCollection = _serviceCollection + // .AddScoped<IReviewService, ReviewService>(); + + return this; + } + + public MockedDependencyInjectionBuilder AddFacades() + { + // Register facade here. + + return this; + } + + } +} diff --git a/TestUtilities/TestUtilities.csproj b/TestUtilities/TestUtilities.csproj new file mode 100644 index 0000000000000000000000000000000000000000..d672305f76d4daa8c616dc694c5e30d9a084a1d3 --- /dev/null +++ b/TestUtilities/TestUtilities.csproj @@ -0,0 +1,19 @@ +<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <TargetFramework>net8.0</TargetFramework> + <ImplicitUsings>enable</ImplicitUsings> + <Nullable>enable</Nullable> + </PropertyGroup> + + <ItemGroup> + <PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="8.0.10" /> + <PackageReference Include="NSubstitute" Version="5.3.0" /> + </ItemGroup> + + <ItemGroup> + <ProjectReference Include="..\BusinessLayer\BusinessLayer.csproj" /> + <ProjectReference Include="..\DAL\DAL.csproj" /> + </ItemGroup> + +</Project> diff --git a/TestUtilities/Usings.cs b/TestUtilities/Usings.cs new file mode 100644 index 0000000000000000000000000000000000000000..08f5c1ae8c78396300734c817546f74e7c37b86c --- /dev/null +++ b/TestUtilities/Usings.cs @@ -0,0 +1 @@ +global using Microsoft.EntityFrameworkCore; \ No newline at end of file