From 54f40a25863558ca10784a6620050f2c088f4c09 Mon Sep 17 00:00:00 2001 From: David Lebee Date: Fri, 23 Nov 2018 10:35:40 -0600 Subject: [PATCH] added unit testing. --- Data.sln | 6 + .../DbContextFactoryPrimaryKeyTests.cs | 37 +++++ .../Mock/Entities.cs | 47 ++++++ .../Mock/MockContext.cs | 32 ++++ .../Mock/MockContextFactory.cs | 25 ++++ .../Mock/TestSeeders.cs | 139 ++++++++++++++++++ .../Mock/Ticket.cs | 36 +++++ ...dSoft.Data.EntityFrameworkCore.Test.csproj | 21 +++ 8 files changed, 343 insertions(+) create mode 100644 PoweredSoft.Data.EntityFrameworkCore.Test/DbContextFactoryPrimaryKeyTests.cs create mode 100644 PoweredSoft.Data.EntityFrameworkCore.Test/Mock/Entities.cs create mode 100644 PoweredSoft.Data.EntityFrameworkCore.Test/Mock/MockContext.cs create mode 100644 PoweredSoft.Data.EntityFrameworkCore.Test/Mock/MockContextFactory.cs create mode 100644 PoweredSoft.Data.EntityFrameworkCore.Test/Mock/TestSeeders.cs create mode 100644 PoweredSoft.Data.EntityFrameworkCore.Test/Mock/Ticket.cs create mode 100644 PoweredSoft.Data.EntityFrameworkCore.Test/PoweredSoft.Data.EntityFrameworkCore.Test.csproj diff --git a/Data.sln b/Data.sln index 6b7c4fa..9fb16fa 100644 --- a/Data.sln +++ b/Data.sln @@ -13,6 +13,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution README.md = README.md EndProjectSection EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PoweredSoft.Data.EntityFrameworkCore.Test", "PoweredSoft.Data.EntityFrameworkCore.Test\PoweredSoft.Data.EntityFrameworkCore.Test.csproj", "{1F0B95F6-2E97-4FC2-A452-F8A071CBEF4B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -27,6 +29,10 @@ Global {78EEC90C-F2C3-4B59-93DA-DE22BFD1FD30}.Debug|Any CPU.Build.0 = Debug|Any CPU {78EEC90C-F2C3-4B59-93DA-DE22BFD1FD30}.Release|Any CPU.ActiveCfg = Release|Any CPU {78EEC90C-F2C3-4B59-93DA-DE22BFD1FD30}.Release|Any CPU.Build.0 = Release|Any CPU + {1F0B95F6-2E97-4FC2-A452-F8A071CBEF4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1F0B95F6-2E97-4FC2-A452-F8A071CBEF4B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1F0B95F6-2E97-4FC2-A452-F8A071CBEF4B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1F0B95F6-2E97-4FC2-A452-F8A071CBEF4B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/PoweredSoft.Data.EntityFrameworkCore.Test/DbContextFactoryPrimaryKeyTests.cs b/PoweredSoft.Data.EntityFrameworkCore.Test/DbContextFactoryPrimaryKeyTests.cs new file mode 100644 index 0000000..79fc463 --- /dev/null +++ b/PoweredSoft.Data.EntityFrameworkCore.Test/DbContextFactoryPrimaryKeyTests.cs @@ -0,0 +1,37 @@ +using PoweredSoft.Test.Mock; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using System.Text; +using Xunit; +using Xunit.Abstractions; + +namespace PoweredSoft.Data.EntityFrameworkCore.Test +{ + public class DbContextFactoryPrimaryKeyTests + { + private readonly ITestOutputHelper output; + + public DbContextFactoryPrimaryKeyTests(ITestOutputHelper output) + { + this.output = output; + } + + [Fact] + public void Simple() + { + MockContextFactory.SeedAndTestContextFor("DbContextFactoryPrimaryKeyTests_Simple", TestSeeders.SimpleSeedScenario, ctx => + { + var sw = new Stopwatch(); + sw.Start(); + var factory = new DbContextFactory(ctx); + var keys = factory.GetKeyProperties(typeof(Order)); + Assert.Single(keys, t => t.Name == "Id"); + sw.Stop(); + output.WriteLine($"Stop Watch of success took: {sw.Elapsed}"); + }); + } + } +} diff --git a/PoweredSoft.Data.EntityFrameworkCore.Test/Mock/Entities.cs b/PoweredSoft.Data.EntityFrameworkCore.Test/Mock/Entities.cs new file mode 100644 index 0000000..aec7dd6 --- /dev/null +++ b/PoweredSoft.Data.EntityFrameworkCore.Test/Mock/Entities.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; + +namespace PoweredSoft.Test.Mock +{ + public class Order + { + public long Id { get; set; } + public long OrderNum { get; set; } + public DateTime Date { get; set; } + public long CustomerId { get; set; } + + public virtual Customer Customer { get; set; } + public ICollection OrderItems { get; set; } = new HashSet(); + } + + public class Customer + { + public long Id { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } + + + public ICollection Orders { get; set; } = new HashSet(); + } + + public class Item + { + public long Id { get; set; } + public string Name { get; set; } + public decimal Price { get; set; } + + public virtual ICollection OrderItems { get; set; } = new HashSet(); + } + + public class OrderItem + { + public long Id { get; set; } + public long Quantity { get; set; } + public decimal PriceAtTheTime { get; set; } + public long ItemId { get; set; } + public long OrderId { get; set; } + + public virtual Item Item { get; set; } + public virtual Order Order { get; set; } + } +} diff --git a/PoweredSoft.Data.EntityFrameworkCore.Test/Mock/MockContext.cs b/PoweredSoft.Data.EntityFrameworkCore.Test/Mock/MockContext.cs new file mode 100644 index 0000000..3e53ebd --- /dev/null +++ b/PoweredSoft.Data.EntityFrameworkCore.Test/Mock/MockContext.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.EntityFrameworkCore; + +namespace PoweredSoft.Test.Mock +{ + public class MockContext : DbContext + { + public virtual DbSet Customers { get; set; } + public virtual DbSet Items { get; set; } + public virtual DbSet Orders { get; set; } + public virtual DbSet OrderItems { get; set; } + public virtual DbSet Tickets { get; set; } + + public MockContext() + { + + } + + public MockContext(DbContextOptions options) + : base(options) + { + + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + + } + } +} diff --git a/PoweredSoft.Data.EntityFrameworkCore.Test/Mock/MockContextFactory.cs b/PoweredSoft.Data.EntityFrameworkCore.Test/Mock/MockContextFactory.cs new file mode 100644 index 0000000..cb569ae --- /dev/null +++ b/PoweredSoft.Data.EntityFrameworkCore.Test/Mock/MockContextFactory.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.EntityFrameworkCore; +using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine.ClientProtocol; +using Xunit.Sdk; + +namespace PoweredSoft.Test.Mock +{ + public static class MockContextFactory + { + public static void TestContextFor(string testName, Action action) + { + var options = new DbContextOptionsBuilder().UseInMemoryDatabase(databaseName: testName).Options; + using (var ctx = new MockContext(options)) + action(ctx); + } + + public static void SeedAndTestContextFor(string testName, Action seedAction, Action action) + { + seedAction(testName); + TestContextFor(testName, action); + } + } +} diff --git a/PoweredSoft.Data.EntityFrameworkCore.Test/Mock/TestSeeders.cs b/PoweredSoft.Data.EntityFrameworkCore.Test/Mock/TestSeeders.cs new file mode 100644 index 0000000..fbd60b1 --- /dev/null +++ b/PoweredSoft.Data.EntityFrameworkCore.Test/Mock/TestSeeders.cs @@ -0,0 +1,139 @@ +using System; +using System.Collections.Generic; + +namespace PoweredSoft.Test.Mock +{ + public static class TestSeeders + { + public static void SimpleSeedScenario(string testName) + { + MockContextFactory.TestContextFor(testName, ctx => + { + ctx.AddRange(new Customer[] + { + new Customer() { Id = 1, FirstName = "David", LastName = "Lebee" }, + new Customer() { Id = 2, FirstName = "John", LastName = "Doe" }, + new Customer() { Id = 3, FirstName = "Chuck", LastName = "Norris" }, + new Customer() { Id = 4, FirstName = "Nelson", LastName = "Mendela" }, + new Customer() { Id = 5, FirstName = "Jimi", LastName = "Hendrix" }, + new Customer() { Id = 6, FirstName = "Axel", LastName = "Rose" }, + new Customer() { Id = 7, FirstName = "John", LastName = "Frusciante" }, + new Customer() { Id = 8, FirstName = "Michael", LastName = "Jackson" }, + new Customer() { Id = 9, FirstName = "Anita", LastName = "Franklin" }, + }); + + ctx.AddRange(new Item[] + { + new Item { Id = 1, Name = "Computer", Price = 1000M }, + new Item { Id = 2, Name = "Mice", Price = 25.99M }, + new Item { Id = 3, Name = "Keyboard", Price = 100M }, + new Item { Id = 4, Name = "Screen", Price = 499.98M }, + new Item { Id = 5, Name = "Printer", Price = 230.95M }, + new Item { Id = 6, Name = "HDMI Cables", Price = 20M }, + new Item { Id = 7, Name = "Power Cables", Price = 5.99M } + }); + + ctx.Orders.AddRange(new Order[] + { + new Order() + { + Id = 1, + OrderNum = 1000, + CustomerId = 1, + Date = new DateTime(2018, 1, 1), + OrderItems = new List() + { + new OrderItem() { Id = 1, ItemId = 1, PriceAtTheTime = 1000M, Quantity = 1 }, + new OrderItem() { Id = 2, ItemId = 2, PriceAtTheTime = 30M, Quantity = 1 }, + new OrderItem() { Id = 3, ItemId = 4, PriceAtTheTime = 399.99M, Quantity = 2 }, + new OrderItem() { Id = 4, ItemId = 6, PriceAtTheTime = 20, Quantity = 2 }, + new OrderItem() { Id = 8, ItemId = 6, PriceAtTheTime = 3.99M, Quantity = 3 } + } + }, + new Order() + { + Id = 2, + OrderNum = 1001, + CustomerId = 2, + Date = new DateTime(2018, 2, 1), + OrderItems = new List() + { + new OrderItem() { Id = 9, ItemId = 6, PriceAtTheTime = 20, Quantity = 2 }, + new OrderItem() { Id = 10, ItemId = 6, PriceAtTheTime = 3.99M, Quantity = 3 } + } + }, + new Order() + { + Id = 3, + OrderNum = 1002, + CustomerId = 3, + Date = new DateTime(2018, 2, 1), + OrderItems = new List() + { + new OrderItem() { Id = 11, ItemId = 5, PriceAtTheTime = 499.99M, Quantity = 1 }, + new OrderItem() { Id = 12, ItemId = 6, PriceAtTheTime = 20, Quantity = 1 }, + new OrderItem() { Id = 13, ItemId = 7, PriceAtTheTime = 3.99M, Quantity = 1 } + } + }, + new Order() + { + Id = 4, + OrderNum = 1003, + CustomerId = 1, + Date = new DateTime(2018, 3, 1), + OrderItems = new List() + { + new OrderItem() { Id = 14, ItemId = 2, PriceAtTheTime = 50M, Quantity = 1 }, + new OrderItem() { Id = 15, ItemId = 3, PriceAtTheTime = 75.50M, Quantity = 1 }, + } + } + }); + + ctx.SaveChanges(); + }); + } + + internal static void SeedTicketScenario(string testName) + { + MockContextFactory.TestContextFor(testName, ctx => + { + var faker = new Bogus.Faker() + .RuleFor(t => t.TicketType, (f, u) => f.PickRandom("new", "open", "refused", "closed")) + .RuleFor(t => t.Title, (f, u) => f.Lorem.Sentence()) + .RuleFor(t => t.Details, (f, u) => f.Lorem.Paragraph()) + .RuleFor(t => t.IsHtml, (f, u) => false) + .RuleFor(t => t.TagList, (f, u) => string.Join(",", f.Commerce.Categories(3))) + .RuleFor(t => t.CreatedDate, (f, u) => f.Date.Recent(100)) + .RuleFor(t => t.Owner, (f, u) => f.Person.FullName) + .RuleFor(t => t.AssignedTo, (f, u) => f.Person.FullName) + .RuleFor(t => t.TicketStatus, (f, u) => f.PickRandom(1, 2, 3)) + .RuleFor(t => t.LastUpdateBy, (f, u) => f.Person.FullName) + .RuleFor(t => t.LastUpdateDate, (f, u) => f.Date.Soon(5)) + .RuleFor(t => t.Priority, (f, u) => f.PickRandom("low", "medium", "high", "critical")) + .RuleFor(t => t.AffectedCustomer, (f, u) => f.PickRandom(true, false)) + .RuleFor(t => t.Version, (f, u) => f.PickRandom("1.0.0", "1.1.0", "2.0.0")) + .RuleFor(t => t.ProjectId, (f, u) => f.Random.Number(100)) + .RuleFor(t => t.DueDate, (f, u) => f.Date.Soon(5)) + .RuleFor(t => t.EstimatedDuration, (f, u) => f.Random.Number(20)) + .RuleFor(t => t.ActualDuration, (f, u) => f.Random.Number(20)) + .RuleFor(t => t.TargetDate, (f, u) => f.Date.Soon(5)) + .RuleFor(t => t.ResolutionDate, (f, u) => f.Date.Soon(5)) + .RuleFor(t => t.Type, (f, u) => f.PickRandom(1, 2, 3)) + .RuleFor(t => t.ParentId, () => 0) + .RuleFor(t => t.PreferredLanguage, (f, u) => f.PickRandom("fr", "en", "es")) + ; + + var fakeModels = new List(); + for (var i = 0; i < 500; i++) + { + var t = faker.Generate(); + t.TicketId = i + 1; + fakeModels.Add(t); + } + + ctx.AddRange(fakeModels); + ctx.SaveChanges(); + }); + } + } +} diff --git a/PoweredSoft.Data.EntityFrameworkCore.Test/Mock/Ticket.cs b/PoweredSoft.Data.EntityFrameworkCore.Test/Mock/Ticket.cs new file mode 100644 index 0000000..cc954cb --- /dev/null +++ b/PoweredSoft.Data.EntityFrameworkCore.Test/Mock/Ticket.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace PoweredSoft.Test.Mock +{ + public class Ticket + { + public int TicketId { get; set; } + public string TicketType { get; set; } + public string Title { get; set; } + public string Details { get; set; } + public bool IsHtml { get; set; } + public string TagList { get; set; } + public DateTimeOffset CreatedDate { get; set; } + public string Owner { get; set; } + public string AssignedTo { get; set; } + public int TicketStatus { get; set; } + public DateTimeOffset CurrentStatusDate { get; set; } + public string CurrentStatusSetBy { get; set; } + public string LastUpdateBy { get; set; } + public DateTimeOffset LastUpdateDate { get; set; } + public string Priority { get; set; } + public bool AffectedCustomer { get; set; } + public string Version { get; set; } + public int ProjectId { get; set; } + public DateTimeOffset DueDate { get; set; } + public decimal EstimatedDuration { get; set; } + public decimal ActualDuration { get; set; } + public DateTimeOffset TargetDate { get; set; } + public DateTimeOffset ResolutionDate { get; set; } + public int Type { get; set; } + public int ParentId { get; set; } + public string PreferredLanguage { get; set; } + } +} diff --git a/PoweredSoft.Data.EntityFrameworkCore.Test/PoweredSoft.Data.EntityFrameworkCore.Test.csproj b/PoweredSoft.Data.EntityFrameworkCore.Test/PoweredSoft.Data.EntityFrameworkCore.Test.csproj new file mode 100644 index 0000000..6b37c54 --- /dev/null +++ b/PoweredSoft.Data.EntityFrameworkCore.Test/PoweredSoft.Data.EntityFrameworkCore.Test.csproj @@ -0,0 +1,21 @@ + + + + netcoreapp2.1 + + false + + + + + + + + + + + + + + +