diff --git a/.github/workflows/build-test-ci.yml b/.github/workflows/build-test-ci.yml new file mode 100644 index 0000000..594f390 --- /dev/null +++ b/.github/workflows/build-test-ci.yml @@ -0,0 +1,30 @@ +name: Build / unit tests + +on: + push: + branches: + - main + pull_request: + branches: + - main +jobs: + build-and-test: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup .NET + uses: actions/setup-dotnet@v1 + with: + dotnet-version: 6.x + + - name: Restore dependencies + run: dotnet restore + + - name: Build + run: dotnet build --configuration Release + + - name: Run tests + run: dotnet test --configuration Release --no-build \ No newline at end of file diff --git a/NorthwindCRUD.Tests/BaseFixture.cs b/NorthwindCRUD.Tests/BaseFixture.cs new file mode 100644 index 0000000..97d4775 --- /dev/null +++ b/NorthwindCRUD.Tests/BaseFixture.cs @@ -0,0 +1,50 @@ +using Microsoft.Data.Sqlite; +using Microsoft.EntityFrameworkCore; +using NorthwindCRUD.Helpers; +using System.Data.Common; + +namespace NorthwindCRUD.Tests +{ + public class BaseFixture + { + private DbConnection? connection; + + protected DataContext GetInMemoryDatabaseContext() + { + if (connection == null) + { + connection = CreateDbConnection(); + var context = CreateInMemoryDatabaseContext(connection); + DBSeeder.Seed(context); + return context; + } + else + { + // Create a new Context on already initialized DB connection + return CreateInMemoryDatabaseContext(connection); + } + } + + protected static DbConnection CreateDbConnection() + { + var connection = new SqliteConnection("DataSource=:memory:"); + connection.Open(); + return connection; + } + + + protected static DataContext CreateInMemoryDatabaseContext(DbConnection connection) + { + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .EnableSensitiveDataLogging() + + // Uncomment the following line for detailed sql EF logs. + // .EnableDetailedErrors().LogTo(Console.WriteLine, LogLevel.Debug) + .Options; + + return new DataContext(options); + } + + } +} diff --git a/NorthwindCRUD.Tests/CategroyServiceFixture.cs b/NorthwindCRUD.Tests/CategroyServiceFixture.cs new file mode 100644 index 0000000..ef0b5d9 --- /dev/null +++ b/NorthwindCRUD.Tests/CategroyServiceFixture.cs @@ -0,0 +1,82 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using NorthwindCRUD.Services; +using NorthwindCRUD.Models.DbModels; + +namespace NorthwindCRUD.Tests +{ + [TestClass] + public class CategoryServiceFixture : BaseFixture + { + private CategoryService categoryService; + + [TestInitialize] + public void Initialize() + { + DataContext context = GetInMemoryDatabaseContext(); + categoryService = new CategoryService(context); + } + + [TestMethod] + public void ShouldCreateCategory() + { + var category = new CategoryDb + { + Name = "New Category", + Description = "New Category Description" + }; + + var createdCategory = categoryService.Create(category); + + var result = categoryService.GetById(createdCategory.CategoryId); + + Assert.IsNotNull(createdCategory); + Assert.AreEqual(category.Name, result.Name); + Assert.AreEqual(category.Description, result.Description); + } + + [TestMethod] + public void ShouldUpdateCategory() + { + var category = new CategoryDb + { + Name = "New Category", + Description = "New Category Description" + }; + var createdCategory = categoryService.Create(category); + + createdCategory.Name = "Updated Category"; + createdCategory.Description = "Updated Description"; + var updatedCategory = categoryService.Update(createdCategory); + + Assert.IsNotNull(updatedCategory); + Assert.AreEqual("Updated Category", updatedCategory.Name); + Assert.AreEqual("Updated Description", updatedCategory.Description); + } + + [TestMethod] + public void ShouldDeleteCategory() + { + var category = new CategoryDb + { + Name = "New Category", + Description = "New Category Description" + }; + + var createdCategory = categoryService.Create(category); + + categoryService.Delete(createdCategory.CategoryId); + var deletedCategory = categoryService.GetById(createdCategory.CategoryId); + + Assert.IsNull(deletedCategory); + } + + [TestMethod] + public void ShouldReturnAllCategories() + { + var result = categoryService.GetAll(); + + Assert.IsNotNull(result); + Assert.IsTrue(result.Count() > 0); + } + } +} \ No newline at end of file diff --git a/NorthwindCRUD.Tests/CustomerServiceFixture.cs b/NorthwindCRUD.Tests/CustomerServiceFixture.cs new file mode 100644 index 0000000..f04e388 --- /dev/null +++ b/NorthwindCRUD.Tests/CustomerServiceFixture.cs @@ -0,0 +1,77 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using NorthwindCRUD.Services; +using NorthwindCRUD.Models.DbModels; + +namespace NorthwindCRUD.Tests +{ + [TestClass] + public class CustomerServiceFixture : BaseFixture + { + private CustomerService customerService; + + [TestInitialize] + public void Initialize() + { + DataContext context = GetInMemoryDatabaseContext(); + customerService = new CustomerService(context); + } + + [TestMethod] + public void ShouldCreateCustomer() + { + var address = new AddressDb + { + Street = "6955 Union Park Center Suite 500", + City = "Midvale", + PostalCode = "84047", + Region = "", + Country = "USA", + Phone = "(800) 231-8588", + }; + + var customer = new CustomerDb + { + CustomerId = "12345", + CompanyName = "Infragistics", + ContactName = "Maria Anders", + ContactTitle = "Sales Representative", + Address = address, + }; + + var createdCustomer = customerService.Create(customer); + + Assert.IsNotNull(createdCustomer); + Assert.AreEqual(customer.CompanyName, createdCustomer.CompanyName); + Assert.AreEqual(customer.ContactName, createdCustomer.ContactName); + Assert.AreEqual(customer.ContactTitle, createdCustomer.ContactTitle); + Assert.AreEqual(customer.Address.Street, createdCustomer.Address.Street); + Assert.AreEqual(customer.Address.City, createdCustomer.Address.City); + Assert.AreEqual(customer.Address.PostalCode, createdCustomer.Address.PostalCode); + Assert.AreEqual(customer.Address.Country, createdCustomer.Address.Country); + Assert.AreEqual(customer.Address.Phone, createdCustomer.Address.Phone); + } + + [TestMethod] + public void ShouldUpdateEmployee() + { + } + + [TestMethod] + public void ShouldDeleteEmployee() + { + } + + [TestMethod] + public void ShouldReturnAllCustomers() + { + var result = customerService.GetAll(); + Assert.IsNotNull(result); + Assert.IsTrue(result.Count() > 0); + } + + [TestMethod] + public void ShouldReturnEmployeesByReportsTo() + { + } + } +} \ No newline at end of file diff --git a/NorthwindCRUD.Tests/EmployeeServiceFixture.cs b/NorthwindCRUD.Tests/EmployeeServiceFixture.cs new file mode 100644 index 0000000..da7bfaa --- /dev/null +++ b/NorthwindCRUD.Tests/EmployeeServiceFixture.cs @@ -0,0 +1,139 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using NorthwindCRUD.Services; +using NorthwindCRUD.Models.DbModels; + +namespace NorthwindCRUD.Tests +{ + [TestClass] + public class EmployeeServiceFixture : BaseFixture + { + private EmployeeService employeeService; + + [TestInitialize] + public void Initialize() + { + DataContext context = GetInMemoryDatabaseContext(); + employeeService = new EmployeeService(context); + } + + [TestMethod] + public void ShouldCreateEmployee() + { + var employee = new EmployeeDb + { + FirstName = "John", + LastName = "Doe", + Title = "Manager" + }; + + var createdEmployee = employeeService.Create(employee); + + Assert.IsNotNull(createdEmployee); + Assert.AreEqual(employee.FirstName, createdEmployee.FirstName); + Assert.AreEqual(employee.LastName, createdEmployee.LastName); + Assert.AreEqual(employee.Title, createdEmployee.Title); + } + + [TestMethod] + public void ShouldUpdateEmployee() + { + var employee = new EmployeeDb + { + FirstName = "John", + LastName = "Doe", + Title = "Manager" + }; + var createdEmployee = employeeService.Create(employee); + + createdEmployee.Title = "Director"; + var updatedEmployee = employeeService.Update(createdEmployee); + + Assert.IsNotNull(updatedEmployee); + Assert.AreEqual("Director", updatedEmployee.Title); + } + + [TestMethod] + public void ShouldDeleteEmployee() + { + var employee = new EmployeeDb + { + FirstName = "John", + LastName = "Doe", + Title = "Manager" + }; + var createdEmployee = employeeService.Create(employee); + + employeeService.Delete(createdEmployee.EmployeeId); + var deletedEmployee = employeeService.GetById(createdEmployee.EmployeeId); + + Assert.IsNull(deletedEmployee); + } + + [TestMethod] + public void ShouldReturnAllEmployees() + { + var result = employeeService.GetAll(); + + Assert.IsNotNull(result); + Assert.IsTrue(result.Count() > 0); + } + + [TestMethod] + public void ShouldReturnEmployeesByReportsTo() + { + var manager = new EmployeeDb + { + FirstName = "Manager", + LastName = "Doe", + Title = "Manager" + }; + + var createdManager = employeeService.Create(manager); + var employee1 = new EmployeeDb + { + FirstName = "Employee1", + LastName = "Smith", + Title = "Employee", + ReportsTo = createdManager.EmployeeId + }; + + var employee2 = new EmployeeDb + { + FirstName = "Employee2", + LastName = "Johnson", + Title = "Employee", + ReportsTo = createdManager.EmployeeId + }; + + + var createdEmployee1 = employeeService.Create(employee1); + var createdEmployee2 = employeeService.Create(employee2); + + + var result = employeeService.GetEmployeesByReportsTo(createdManager.EmployeeId); + + Assert.IsNotNull(result); + Assert.AreEqual(2, result.Count()); + Assert.IsTrue(result.All(e => e.ReportsTo == createdManager.EmployeeId)); + } + + [TestMethod] + public void ShouldReturnEmployeeById() + { + var employee = new EmployeeDb + { + FirstName = "John", + LastName = "Doe", + Title = "Manager" + }; + var createdEmployee = employeeService.Create(employee); + + var result = employeeService.GetById(createdEmployee.EmployeeId); + + Assert.IsNotNull(result); + Assert.AreEqual("John", result.FirstName); + Assert.AreEqual("Doe", result.LastName); + Assert.AreEqual("Manager", result.Title); + } + } +} \ No newline at end of file diff --git a/NorthwindCRUD.Tests/EmployeeTerritoryServiceFixture.cs b/NorthwindCRUD.Tests/EmployeeTerritoryServiceFixture.cs new file mode 100644 index 0000000..154f67a --- /dev/null +++ b/NorthwindCRUD.Tests/EmployeeTerritoryServiceFixture.cs @@ -0,0 +1,120 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using NorthwindCRUD.Services; +using NorthwindCRUD.Models.DbModels; + +namespace NorthwindCRUD.Tests +{ + [TestClass] + public class EmployeeTerritoryServiceFixture : BaseFixture + { + private EmployeeTerritoryService employeeTerritoryService; + private EmployeeService employeeService; + private TerritoryService territoryService; + + [TestInitialize] + public void Initialize() + { + DataContext context = GetInMemoryDatabaseContext(); + employeeService = new EmployeeService(context); + territoryService = new TerritoryService(context); + employeeTerritoryService = new EmployeeTerritoryService(context); + } + + static T GetRandomElement(T[] array) + { + if (array == null || array.Length == 0) + { + throw new ArgumentException("The array cannot be null or empty."); + } + + Random random = new Random(); + int randomIndex = random.Next(array.Length); + return array[randomIndex]; + } + + [TestMethod] + public void ShouldAddTerritoryToEmployee() + { + var employeeId = GetRandomElement(employeeService.GetAll()).EmployeeId; + var territoryId = GetRandomElement(territoryService.GetAll()).TerritoryId; + + var employeeTerritory = new EmployeeTerritoryDb + { + EmployeeId = employeeId, + TerritoryId = territoryId, + }; + + employeeTerritoryService.AddTerritoryToEmployee(employeeTerritory); + + var territories = employeeTerritoryService.GetTeritoriesByEmployeeId(employeeId); + Assert.IsNotNull(territories); + Assert.IsTrue(territories.Any(t => t.TerritoryId == territoryId)); + } + + [TestMethod] + public void ShouldReturnTerritoriesForEmployee() + { + var employeeId = GetRandomElement(employeeService.GetAll()).EmployeeId; + var territoryId1 = GetRandomElement(territoryService.GetAll()).TerritoryId; + var territoryId2 = GetRandomElement(territoryService.GetAll()).TerritoryId; + + var initialTerritoryCount = employeeTerritoryService.GetTeritoriesByEmployeeId(employeeId).Count(); + + var employeeTerritory = new EmployeeTerritoryDb + { + EmployeeId = employeeId, + TerritoryId = territoryId1, + }; + + employeeTerritoryService.AddTerritoryToEmployee(employeeTerritory); + + employeeTerritory = new EmployeeTerritoryDb + { + EmployeeId = employeeId, + TerritoryId = territoryId2, + }; + + employeeTerritoryService.AddTerritoryToEmployee(employeeTerritory); + + var territories = employeeTerritoryService.GetTeritoriesByEmployeeId(employeeId); + + Assert.IsNotNull(territories); + Assert.AreEqual(initialTerritoryCount + 2, territories.Count()); + Assert.IsTrue(territories.Any(t => t.TerritoryId == territoryId1)); + Assert.IsTrue(territories.Any(t => t.TerritoryId == territoryId2)); + } + + [TestMethod] + public void ShouldReturnEmployeesForTerritory() + { + var employeeId1 = GetRandomElement(employeeService.GetAll()).EmployeeId; + var employeeId2= GetRandomElement(employeeService.GetAll()).EmployeeId; + var territoryId = GetRandomElement(territoryService.GetAll()).TerritoryId; + + var initialEmployeeCount = employeeTerritoryService.GetEmployeesByTerritoryId(territoryId).Count(); + + var employeeTerritory = new EmployeeTerritoryDb + { + EmployeeId = employeeId1, + TerritoryId = territoryId, + }; + + employeeTerritoryService.AddTerritoryToEmployee(employeeTerritory); + + employeeTerritory = new EmployeeTerritoryDb + { + EmployeeId = employeeId2, + TerritoryId = territoryId, + }; + + employeeTerritoryService.AddTerritoryToEmployee(employeeTerritory); + + var employees = employeeTerritoryService.GetEmployeesByTerritoryId(territoryId); + + Assert.IsNotNull(employees); + Assert.AreEqual(initialEmployeeCount + 2, employees.Count()); + Assert.IsTrue(employees.Any(e => e.EmployeeId == employeeId1)); + Assert.IsTrue(employees.Any(e => e.EmployeeId == employeeId2)); + } + } +} \ No newline at end of file diff --git a/NorthwindCRUD.Tests/NorthwindCRUD.Tests.csproj b/NorthwindCRUD.Tests/NorthwindCRUD.Tests.csproj new file mode 100644 index 0000000..9e0ec45 --- /dev/null +++ b/NorthwindCRUD.Tests/NorthwindCRUD.Tests.csproj @@ -0,0 +1,22 @@ + + + + net6.0 + enable + enable + + false + + + + + + + + + + + + + + diff --git a/NorthwindCRUD.sln b/NorthwindCRUD.sln index 365eb8b..82f9b68 100644 --- a/NorthwindCRUD.sln +++ b/NorthwindCRUD.sln @@ -3,7 +3,14 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.2.32526.322 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NorthwindCRUD", "NorthwindCRUD\NorthwindCRUD.csproj", "{43E42C18-0E59-4754-ADF1-25D90114F7E8}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NorthwindCRUD", "NorthwindCRUD\NorthwindCRUD.csproj", "{43E42C18-0E59-4754-ADF1-25D90114F7E8}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NorthwindCRUD.Tests", "NorthwindCRUD.Tests\NorthwindCRUD.Tests.csproj", "{F2C392E4-219B-41F3-8010-10E69EBF434D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Github Workflows", "Github Workflows", "{816E41A3-F9E9-4244-88C7-930196599CFF}" + ProjectSection(SolutionItems) = preProject + .github\workflows\build-test-ci.yml = .github\workflows\build-test-ci.yml + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -15,6 +22,10 @@ Global {43E42C18-0E59-4754-ADF1-25D90114F7E8}.Debug|Any CPU.Build.0 = Debug|Any CPU {43E42C18-0E59-4754-ADF1-25D90114F7E8}.Release|Any CPU.ActiveCfg = Release|Any CPU {43E42C18-0E59-4754-ADF1-25D90114F7E8}.Release|Any CPU.Build.0 = Release|Any CPU + {F2C392E4-219B-41F3-8010-10E69EBF434D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F2C392E4-219B-41F3-8010-10E69EBF434D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F2C392E4-219B-41F3-8010-10E69EBF434D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F2C392E4-219B-41F3-8010-10E69EBF434D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/NorthwindCRUD/Services/CategoryService.cs b/NorthwindCRUD/Services/CategoryService.cs index 9a5b406..05056c1 100644 --- a/NorthwindCRUD/Services/CategoryService.cs +++ b/NorthwindCRUD/Services/CategoryService.cs @@ -1,18 +1,15 @@ namespace NorthwindCRUD.Services { - using AutoMapper; using NorthwindCRUD.Helpers; using NorthwindCRUD.Models.DbModels; public class CategoryService { - private readonly IMapper mapper; private readonly DataContext dataContext; - public CategoryService(IMapper mapper, DataContext dataContext) + public CategoryService(DataContext dataContext) { - this.mapper = mapper; this.dataContext = dataContext; } diff --git a/NorthwindCRUD/Services/EmployeeTerritoryService.cs b/NorthwindCRUD/Services/EmployeeTerritoryService.cs index df4f47a..b7f3fae 100644 --- a/NorthwindCRUD/Services/EmployeeTerritoryService.cs +++ b/NorthwindCRUD/Services/EmployeeTerritoryService.cs @@ -1,20 +1,15 @@ -namespace NorthwindCRUD.Services -{ - using AutoMapper; - using Microsoft.EntityFrameworkCore; - using NorthwindCRUD.Constants; - using NorthwindCRUD.Models.Contracts; - using NorthwindCRUD.Models.DbModels; - +using Microsoft.EntityFrameworkCore; +using NorthwindCRUD.Constants; +using NorthwindCRUD.Models.DbModels; +namespace NorthwindCRUD.Services +{ public class EmployeeTerritoryService { - private readonly IMapper mapper; private readonly DataContext dataContext; - public EmployeeTerritoryService(IMapper mapper, DataContext dataContext) + public EmployeeTerritoryService(DataContext dataContext) { - this.mapper = mapper; this.dataContext = dataContext; } diff --git a/NorthwindCRUD/Services/TerritoryService.cs b/NorthwindCRUD/Services/TerritoryService.cs index a2485fc..6e56698 100644 --- a/NorthwindCRUD/Services/TerritoryService.cs +++ b/NorthwindCRUD/Services/TerritoryService.cs @@ -1,21 +1,16 @@ -namespace NorthwindCRUD.Services -{ - using AutoMapper; - using Microsoft.EntityFrameworkCore; - using NorthwindCRUD.Constants; - using NorthwindCRUD.Helpers; - using NorthwindCRUD.Models.DbModels; - using NorthwindCRUD.Models.Dtos; +using NorthwindCRUD.Constants; +using NorthwindCRUD.Helpers; +using NorthwindCRUD.Models.DbModels; +namespace NorthwindCRUD.Services +{ public class TerritoryService { - private readonly IMapper mapper; private readonly DataContext dataContext; - public TerritoryService(IMapper mapper, DataContext dataContext) + public TerritoryService(DataContext dataContext) { - this.mapper = mapper; this.dataContext = dataContext; }