Skip to content

Commit

Permalink
[DEV-4616]Add support for async flow. (#17)
Browse files Browse the repository at this point in the history
  • Loading branch information
yyosifov1979 authored Jan 17, 2023
1 parent 7b353e8 commit 5ded264
Show file tree
Hide file tree
Showing 26 changed files with 849 additions and 12 deletions.
2 changes: 2 additions & 0 deletions src/Easify.Ef.Testing.UnitTests/DbContextExtensionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//

using Easify.Ef.UnitOfWork;

namespace Easify.Ef.Testing.UnitTests;

public class DbContextExtensionsTests
Expand Down
2 changes: 2 additions & 0 deletions src/Easify.Ef.Testing.UnitTests/Models/SampleDbContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//

using Easify.Http;

namespace Easify.Ef.Testing.UnitTests.Models;

public class SampleDbContext : DbContextBase
Expand Down
3 changes: 0 additions & 3 deletions src/Easify.Ef.Testing.UnitTests/Usings.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
global using Easify.Ef.Testing.UnitTests.Models;
global using Easify.Ef.Testing.Extensions;
global using Easify.Http;

global using Microsoft.EntityFrameworkCore;
global using Microsoft.Extensions.DependencyInjection;

global using EfCore.UnitOfWork;
global using FluentAssertions;
global using Xunit;
2 changes: 2 additions & 0 deletions src/Easify.Ef.Testing/Extensions/EntityListExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//

using Easify.Ef.UnitOfWork;

namespace Easify.Ef.Testing.Extensions;

public static class EntityListExtensions
Expand Down
2 changes: 1 addition & 1 deletion src/Easify.Ef.Testing/Usings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
global using Microsoft.Extensions.DependencyInjection;
global using Microsoft.Extensions.DependencyInjection.Extensions;

global using EfCore.UnitOfWork;
global using Easify.Ef.UnitOfWork;
global using AutoMapper;
13 changes: 13 additions & 0 deletions src/Easify.Ef.UnitTests/UnitOfWork/Entities/City.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System.Collections.Generic;

namespace Easify.Ef.UnitOfWork.UnitTests.Entities
{
public class City
{
public int Id { get; set; }
public string Name { get; set; }
public int CountryId { get; set; }
public Country Country { get; set; }
public List<Town> Towns { get; set; }
}
}
13 changes: 13 additions & 0 deletions src/Easify.Ef.UnitTests/UnitOfWork/Entities/Country.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace Easify.Ef.UnitOfWork.UnitTests.Entities
{
public class Country
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public List<City> Cities { get; set; }
}
}
9 changes: 9 additions & 0 deletions src/Easify.Ef.UnitTests/UnitOfWork/Entities/Customer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Easify.Ef.UnitOfWork.UnitTests.Entities
{
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
}
10 changes: 10 additions & 0 deletions src/Easify.Ef.UnitTests/UnitOfWork/Entities/Town.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace Easify.Ef.UnitOfWork.UnitTests.Entities
{
public class Town
{
public int Id { get; set; }
public string Name { get; set; }
public int CityId { get; set; }
public City City { get; set; }
}
}
27 changes: 27 additions & 0 deletions src/Easify.Ef.UnitTests/UnitOfWork/InMemoryDbContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System;
using Easify.Ef.UnitOfWork.UnitTests.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.Extensions.DependencyInjection;

namespace Easify.Ef.UnitOfWork.UnitTests
{
public class InMemoryDbContext : DbContext
{
public DbSet<Country> Countries { get; set; }
public DbSet<Customer> Customers { get; set; }

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
var name = $"{nameof(InMemoryDbContext)}_{Guid.NewGuid()}";

var serviceProvider = new ServiceCollection()
.AddEntityFrameworkInMemoryDatabase()
.BuildServiceProvider();

optionsBuilder.UseInMemoryDatabase(name)
.ConfigureWarnings(warnings => warnings.Ignore(InMemoryEventId.TransactionIgnoredWarning))
.UseInternalServiceProvider(serviceProvider);
}
}
}
50 changes: 50 additions & 0 deletions src/Easify.Ef.UnitTests/UnitOfWork/RepositoryFixture.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using Easify.Ef.UnitOfWork.UnitTests.Entities;

namespace Easify.Ef.UnitOfWork.UnitTests
{
public class RepositoryFixture
{
private static IEnumerable<Country> TestCountries => new List<Country>
{
new Country {Id = 1, Name = "A"},
new Country {Id = 2, Name = "B"}
};

private static IEnumerable<City> TestCities => new List<City>
{
new City { Id = 1, Name = "A", CountryId = 1},
new City { Id = 2, Name = "B", CountryId = 2},
new City { Id = 3, Name = "C", CountryId = 1},
new City { Id = 4, Name = "D", CountryId = 2},
new City { Id = 5, Name = "E", CountryId = 1},
new City { Id = 6, Name = "F", CountryId = 2},
};

private static IEnumerable<Town> TestTowns => new List<Town>
{
new Town { Id = 1, Name="A", CityId = 1 },
new Town { Id = 2, Name="B", CityId = 2 },
new Town { Id = 3, Name="C", CityId = 3 },
new Town { Id = 4, Name="D", CityId = 4 },
new Town { Id = 5, Name="E", CityId = 5 },
new Town { Id = 6, Name="F", CityId = 6 },
};

public InMemoryDbContext DbContext()
{
var dbContext = new InMemoryDbContext();

dbContext.AddRange(TestCountries);
dbContext.AddRange(TestCities);
dbContext.AddRange(TestTowns);

dbContext.SaveChanges();

return dbContext;
}

public IUnitOfWork CreateUnitOfWork() => new UnitOfWork<InMemoryDbContext>(DbContext());

public IRepository<T> CreateRepository<T>() where T : class => new Repository<T>(DbContext());
}
}
171 changes: 171 additions & 0 deletions src/Easify.Ef.UnitTests/UnitOfWork/RepositoryTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
using System.Threading.Tasks;
using Easify.Ef.UnitOfWork.UnitTests.Entities;
using Easify.Ef.UnitOfWork.Extensions;
using FluentAssertions;
using Microsoft.EntityFrameworkCore;
using Xunit;

namespace Easify.Ef.UnitOfWork.UnitTests
{
public class RepositoryTests : IClassFixture<RepositoryFixture>
{
private readonly RepositoryFixture _fixture;

public RepositoryTests(RepositoryFixture fixture)
{
_fixture = fixture;
}

[Fact]
public void Should_GetList_ResolveTheRightSetOfDataFromContext()
{
// Arrange
var repository = _fixture.CreateRepository<City>();

// Act
var actual = repository.GetList(t => t.Name == "C", q => q.Include(t => t.Country).PagedBy(0, 1));

// Assert

actual.Should().HaveCount(1)
.And.Contain(m => m.Country != null && m.CountryId != 0 && m.Country.Name == "A" && m.Country.Id == 1);
}

[Fact]
public async Task Should_GetListAsync_ResolveTheRightSetOfDataFromContext()
{
// Arrange
var repository = _fixture.CreateRepository<City>();

// Act
var actual =
await repository.GetListAsync(t => t.Name == "C", q => q.Include(t => t.Country).PagedBy(0, 1));

// Assert

actual.Should().HaveCount(1)
.And.Contain(m => m.Country != null && m.CountryId != 0 && m.Country.Name == "A" && m.Country.Id == 1);
}

[Fact]
public void Should_GetProjectedList_WithProjection_ResolveTheSmallerSetOfDataFromContext()
{
// Arrange
var repository = _fixture.CreateRepository<City>();

// Act
var actual = repository.GetProjectedList(t => t.Name == "C", m => m.Name, q => q.Include(t => t.Country));

// Assert
actual.Should().HaveCount(1)
.And.Contain(m => m == "C");
}

[Fact]
public async Task Should_GetProjectedListAsync_WithProjection_ResolveTheSmallerSetOfDataFromContext()
{
// Arrange
var repository = _fixture.CreateRepository<City>();

// Act
var actual =
await repository.GetProjectedListAsync(t => t.Name == "C", m => m.Name);
// await repository.GetProjectedListAsync(t => t.Name == "C", m => m.Name, q => q.Include(t => t.Country));

// Assert
actual.Should().HaveCount(1)
.And.Contain(m => m == "C");
}

[Fact]
public void Should_GetFirstOrDefault_ResolveTheRightSetOfDataFromContext()
{
// Arrange
var repository = _fixture.CreateRepository<City>();

// Act
var actual = repository.GetFirstOrDefault(t => t.Name == "C", q => q.Include(t => t.Country));

// Assert
actual.Should().NotBeNull();
actual.Name.Should().Be("C");
actual.CountryId.Should().Be(1);
actual.Country.Should().BeEquivalentTo(new Country {Name = "A", Id = 1}, m => m.Excluding(t => t.Cities));
}

[Fact]
public async Task Should_GetFirstOrDefaultAsync_ResolveTheRightSetOfDataFromContext()
{
// Arrange
var repository = _fixture.CreateRepository<City>();

// Act
var actual = await repository.GetFirstOrDefaultAsync(t => t.Name == "C", q => q.Include(t => t.Country));

// Assert
actual.Should().NotBeNull();
actual.Name.Should().Be("C");
actual.CountryId.Should().Be(1);
actual.Country.Should().BeEquivalentTo(new Country {Name = "A", Id = 1}, m => m.Excluding(t => t.Cities));
}

[Fact]
public async Task Should_GetFirstOrDefaultAsync_ReturnsMultipleLevelOfHierarchyWhenItsIncludedInQuery()
{
// Arrange
var repository = _fixture.CreateRepository<Country>();

// Act
var actual = await repository.GetFirstOrDefaultAsync(t => t.Name == "A",
country => country.Include(c => c.Cities).ThenInclude(city => city.Towns));

// Assert
actual.Should().NotBeNull();
actual.Cities.Should().HaveCount(3).And.Contain(m => m.Towns.Count == 1);
}

[Fact]
public void Should_Find_ReturnsCertainEntityByIdentifier()
{
// Arrange
var repository = _fixture.CreateRepository<Country>();

// Act
var actual = repository.Find(1);

// Assert
actual.Should().NotBeNull();
actual.Name.Should().Be("A");
}

[Fact]
public async Task Should_FindAsync_ReturnsCertainEntityByIdentifier()
{
// Arrange
var repository = _fixture.CreateRepository<Country>();

// Act
var actual = await repository.FindAsync(1);

// Assert
actual.Should().NotBeNull();
actual.Name.Should().Be("A");
}

[Theory]
[InlineData("A", 1)]
[InlineData("B", 1)]
[InlineData("C", 0)]
public void Should_Count_ReturnsTheNumberOfRecordsAccordingly(string phrase, int expectedCount)
{
// Arrange
var repository = _fixture.CreateRepository<Country>();

// Act
var actual = repository.Count(m => m.Name == phrase);

// Assert
actual.Should().Be(expectedCount);
}
}
}
Loading

0 comments on commit 5ded264

Please sign in to comment.