diff --git a/src/MockQueryable/MockQueryable.Core/TestQueryProvider.cs b/src/MockQueryable/MockQueryable.Core/TestQueryProvider.cs index 264b051..92a5a95 100644 --- a/src/MockQueryable/MockQueryable.Core/TestQueryProvider.cs +++ b/src/MockQueryable/MockQueryable.Core/TestQueryProvider.cs @@ -6,8 +6,9 @@ namespace MockQueryable.Core { - public abstract class TestQueryProvider : IOrderedQueryable, IQueryProvider - { + public abstract class TestQueryProvider : IOrderedQueryable, IQueryProvider + where TExpressionVisitor : ExpressionVisitor, new() + { private IEnumerable _enumerable; protected TestQueryProvider(Expression expression) @@ -40,7 +41,7 @@ public IQueryable CreateQuery(Expression expression) private object CreateInstance(Type tElement, Expression expression) { - var queryType = GetType().GetGenericTypeDefinition().MakeGenericType(tElement); + var queryType = GetType().GetGenericTypeDefinition().MakeGenericType(tElement, typeof(TExpressionVisitor)); return Activator.CreateInstance(queryType, expression); } @@ -74,7 +75,7 @@ IEnumerator IEnumerable.GetEnumerator() private static TResult CompileExpressionItem(Expression expression) { - var visitor = new TestExpressionVisitor(); + var visitor = new TExpressionVisitor(); var body = visitor.Visit(expression); var f = Expression.Lambda>(body ?? throw new InvalidOperationException($"{nameof(body)} is null"), (IEnumerable) null); return f.Compile()(); diff --git a/src/MockQueryable/MockQueryable.EntityFrameworkCore/MockQueryable.EntityFrameworkCore.csproj b/src/MockQueryable/MockQueryable.EntityFrameworkCore/MockQueryable.EntityFrameworkCore.csproj index 88963b3..b1aaa83 100644 --- a/src/MockQueryable/MockQueryable.EntityFrameworkCore/MockQueryable.EntityFrameworkCore.csproj +++ b/src/MockQueryable/MockQueryable.EntityFrameworkCore/MockQueryable.EntityFrameworkCore.csproj @@ -1,7 +1,7 @@ - net6 + net8 MockQueryable.EntityFrameworkCore Roman Titov @@ -45,7 +45,7 @@ - + diff --git a/src/MockQueryable/MockQueryable.EntityFrameworkCore/MockQueryableExtensions.cs b/src/MockQueryable/MockQueryable.EntityFrameworkCore/MockQueryableExtensions.cs index c94b1c8..93157df 100644 --- a/src/MockQueryable/MockQueryable.EntityFrameworkCore/MockQueryableExtensions.cs +++ b/src/MockQueryable/MockQueryable.EntityFrameworkCore/MockQueryableExtensions.cs @@ -1,6 +1,8 @@ -using MockQueryable.EntityFrameworkCore; +using MockQueryable.Core; +using MockQueryable.EntityFrameworkCore; using System.Collections.Generic; using System.Linq; +using System.Linq.Expressions; // Moving MockQueryableExtensions BuildMock into the MockQueryable.EntityFrameworkCore // namespace had breaking changes with earlier extensions added to MockQueryable.Moq @@ -9,11 +11,19 @@ // is dependent on the EF Core AsyncEnumerable. namespace MockQueryable { - public static class MockQueryableExtensions + public static class MockQueryableExtensions + { + public static IQueryable BuildMock(this IEnumerable data) + where TEntity : class { - public static IQueryable BuildMock(this IEnumerable data) where TEntity : class - { - return new TestAsyncEnumerableEfCore(data); - } + return new TestAsyncEnumerableEfCore(data); } + + public static IQueryable BuildMock(this IEnumerable data) + where TEntity : class + where TExpressionVisitor : ExpressionVisitor, new() + { + return new TestAsyncEnumerableEfCore(data); + } + } } diff --git a/src/MockQueryable/MockQueryable.EntityFrameworkCore/TestQueryProviderEfCore.cs b/src/MockQueryable/MockQueryable.EntityFrameworkCore/TestQueryProviderEfCore.cs index 9b637ba..038b856 100644 --- a/src/MockQueryable/MockQueryable.EntityFrameworkCore/TestQueryProviderEfCore.cs +++ b/src/MockQueryable/MockQueryable.EntityFrameworkCore/TestQueryProviderEfCore.cs @@ -8,7 +8,8 @@ namespace MockQueryable.EntityFrameworkCore { - public class TestAsyncEnumerableEfCore: TestQueryProvider, IAsyncEnumerable, IAsyncQueryProvider + public class TestAsyncEnumerableEfCore: TestQueryProvider, IAsyncEnumerable, IAsyncQueryProvider + where TExpressionVisitor : ExpressionVisitor, new() { public TestAsyncEnumerableEfCore(Expression expression) : base(expression) { @@ -25,11 +26,11 @@ public TResult ExecuteAsync(Expression expression, CancellationToken ca .GetMethods() .First(method => method.Name == nameof(IQueryProvider.Execute) && method.IsGenericMethod) .MakeGenericMethod(expectedResultType) - .Invoke(this, new object[] { expression }); + .Invoke(this, [expression]); return (TResult)typeof(Task).GetMethod(nameof(Task.FromResult)) .MakeGenericMethod(expectedResultType) - .Invoke(null, new[] { executionResult }); + .Invoke(null, [executionResult]); } public IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) diff --git a/src/MockQueryable/MockQueryable.FakeItEasy/FakeItEasyExtensions.cs b/src/MockQueryable/MockQueryable.FakeItEasy/FakeItEasyExtensions.cs index ee8c1b0..2fd7c40 100644 --- a/src/MockQueryable/MockQueryable.FakeItEasy/FakeItEasyExtensions.cs +++ b/src/MockQueryable/MockQueryable.FakeItEasy/FakeItEasyExtensions.cs @@ -1,68 +1,105 @@ using FakeItEasy; using Microsoft.EntityFrameworkCore; +using MockQueryable.Core; using MockQueryable.EntityFrameworkCore; using System.Collections.Generic; using System.Linq; +using System.Linq.Expressions; using System.Threading; using System.Threading.Tasks; namespace MockQueryable.FakeItEasy { - public static class FakeItEasyExtensions + public static class FakeItEasyExtensions + { + public static DbSet BuildMockDbSet(this IEnumerable data) + where TEntity : class + where TExpressionVisitor : ExpressionVisitor, new() + => data.BuildMock().BuildMockDbSet(); + + public static DbSet BuildMockDbSet(this IEnumerable data) + where TEntity : class + => data.BuildMock().BuildMockDbSet(); + + /// + /// This method allows you to create a mock DbSet for testing purposes. + /// It is particularly useful when you want to simulate the behavior of Entity Framework Core's DbSet + /// with custom expression handling, such as for testing LINQ queries or database operations. + /// The method takes an IQueryable of the entity type and returns a mocked DbSet that implements + /// both IAsyncEnumerable and IQueryable interfaces, allowing for asynchronous enumeration + /// and LINQ query capabilities. + /// + /// + /// The type of the entity that the DbSet will represent. + /// + public static DbSet BuildMockDbSet(this IQueryable data) where TEntity : class { - public static DbSet BuildMockDbSet(this IEnumerable data) where TEntity : class => data.BuildMock().BuildMockDbSet(); + return BuildMockDbSet(data); + } - public static DbSet BuildMockDbSet(this IQueryable data) where TEntity : class - { - var mock = A.Fake>(d => d.Implements>().Implements>()); - var enumerable = new TestAsyncEnumerableEfCore(data); - mock.ConfigureQueryableCalls(enumerable, data); - mock.ConfigureAsyncEnumerableCalls(enumerable); - mock.ConfigureDbSetCalls(data); - if (mock is IAsyncEnumerable asyncEnumerable) - { - A.CallTo(() => asyncEnumerable.GetAsyncEnumerator(A.Ignored)).ReturnsLazily(() => enumerable.GetAsyncEnumerator()); - } - return mock; - } + /// + /// See . + /// + /// + /// The type of the entity that the DbSet will represent. + /// + /// + /// The type of the expression visitor that will be used to process LINQ expressions. + /// Can be used to mock EF Core specific expression handling, such as for ILike expressions. + /// + public static DbSet BuildMockDbSet(this IQueryable data) + where TEntity : class + where TExpressionVisitor : ExpressionVisitor, new() + { + var mock = A.Fake>(d => d.Implements>().Implements>()); + var enumerable = new TestAsyncEnumerableEfCore(data); + mock.ConfigureQueryableCalls(enumerable, data); + mock.ConfigureAsyncEnumerableCalls(enumerable); + mock.ConfigureDbSetCalls(data); + if (mock is IAsyncEnumerable asyncEnumerable) + { + A.CallTo(() => asyncEnumerable.GetAsyncEnumerator(A.Ignored)).ReturnsLazily(() => enumerable.GetAsyncEnumerator()); + } - private static void ConfigureQueryableCalls( - this IQueryable mock, - IQueryProvider queryProvider, - IQueryable data) where TEntity : class - { - A.CallTo(() => mock.Provider).Returns(queryProvider); - A.CallTo(() => mock.Expression).Returns(data?.Expression); - A.CallTo(() => mock.ElementType).Returns(data?.ElementType); - A.CallTo(() => mock.GetEnumerator()).ReturnsLazily(() => data?.GetEnumerator()); - } + return mock; + } - private static void ConfigureAsyncEnumerableCalls( - this DbSet mock, - IAsyncEnumerable enumerable) where TEntity : class - { - A.CallTo(() => mock.GetAsyncEnumerator(A.Ignored)) - .Returns(enumerable.GetAsyncEnumerator()); - - } + private static void ConfigureQueryableCalls( + this IQueryable mock, + IQueryProvider queryProvider, + IQueryable data) where TEntity : class + { + A.CallTo(() => mock.Provider).Returns(queryProvider); + A.CallTo(() => mock.Expression).Returns(data?.Expression); + A.CallTo(() => mock.ElementType).Returns(data?.ElementType); + A.CallTo(() => mock.GetEnumerator()).ReturnsLazily(() => data?.GetEnumerator()); + } - private static void ConfigureDbSetCalls(this DbSet mock, IQueryable data) - where TEntity : class - { - A.CallTo(() => mock.AsQueryable()).Returns(data); - A.CallTo(() => mock.AsAsyncEnumerable()).ReturnsLazily(args => CreateAsyncMock(data)); - } + private static void ConfigureAsyncEnumerableCalls( + this DbSet mock, + IAsyncEnumerable enumerable) where TEntity : class + { + A.CallTo(() => mock.GetAsyncEnumerator(A.Ignored)) + .Returns(enumerable.GetAsyncEnumerator()); + } + + private static void ConfigureDbSetCalls(this DbSet mock, IQueryable data) + where TEntity : class + { + A.CallTo(() => mock.AsQueryable()).Returns(data); + A.CallTo(() => mock.AsAsyncEnumerable()).ReturnsLazily(args => CreateAsyncMock(data)); + } - private static async IAsyncEnumerable CreateAsyncMock(IEnumerable data) - where TEntity : class - { - foreach (var entity in data) - { - yield return entity; - } + private static async IAsyncEnumerable CreateAsyncMock(IEnumerable data) + where TEntity : class + { + foreach (var entity in data) + { + yield return entity; + } - await Task.CompletedTask; - } + await Task.CompletedTask; } + } } \ No newline at end of file diff --git a/src/MockQueryable/MockQueryable.FakeItEasy/MockQueryable.FakeItEasy.csproj b/src/MockQueryable/MockQueryable.FakeItEasy/MockQueryable.FakeItEasy.csproj index dbfedb2..eea1d69 100644 --- a/src/MockQueryable/MockQueryable.FakeItEasy/MockQueryable.FakeItEasy.csproj +++ b/src/MockQueryable/MockQueryable.FakeItEasy/MockQueryable.FakeItEasy.csproj @@ -1,7 +1,7 @@  - net6 + net8 MockQueryable.FakeItEasy Roman Titov @@ -26,7 +26,7 @@ - + diff --git a/src/MockQueryable/MockQueryable.Moq/MockQueryable.Moq.csproj b/src/MockQueryable/MockQueryable.Moq/MockQueryable.Moq.csproj index c9c2fa6..55adeec 100644 --- a/src/MockQueryable/MockQueryable.Moq/MockQueryable.Moq.csproj +++ b/src/MockQueryable/MockQueryable.Moq/MockQueryable.Moq.csproj @@ -1,7 +1,7 @@  - net6 + net8 MockQueryable.Moq Roman Titov @@ -26,7 +26,7 @@ - + diff --git a/src/MockQueryable/MockQueryable.Moq/MoqExtensions.cs b/src/MockQueryable/MockQueryable.Moq/MoqExtensions.cs index dafd6b0..c169f3b 100644 --- a/src/MockQueryable/MockQueryable.Moq/MoqExtensions.cs +++ b/src/MockQueryable/MockQueryable.Moq/MoqExtensions.cs @@ -1,32 +1,69 @@ -using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; +using MockQueryable.Core; +using MockQueryable.EntityFrameworkCore; +using Moq; +using System.Collections.Generic; using System.Linq; +using System.Linq.Expressions; using System.Threading; using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore; -using MockQueryable.EntityFrameworkCore; -using Moq; namespace MockQueryable.Moq { public static class MoqExtensions { - public static Mock> BuildMockDbSet(this IEnumerable data) where TEntity : class => data.BuildMock().BuildMockDbSet(); + public static Mock> BuildMockDbSet(this IEnumerable data) + where TEntity : class + where TExpressionVisitor : ExpressionVisitor, new() + => data.BuildMock().BuildMockDbSet(); - public static Mock> BuildMockDbSet(this IQueryable data) where TEntity : class + public static Mock> BuildMockDbSet(this IEnumerable data) + where TEntity : class + => data.BuildMock().BuildMockDbSet(); + + /// + /// This method allows you to create a mock DbSet for testing purposes. + /// It is particularly useful when you want to simulate the behavior of Entity Framework Core's DbSet + /// with custom expression handling, such as for testing LINQ queries or database operations. + /// The method takes an IQueryable of the entity type and returns a mocked DbSet that implements + /// both IAsyncEnumerable and IQueryable interfaces, allowing for asynchronous enumeration + /// and LINQ query capabilities. + /// + /// + /// The type of the entity that the DbSet will represent. + /// + public static Mock> BuildMockDbSet(this IQueryable data) where TEntity : class { - var mock = new Mock>(); - var enumerable = new TestAsyncEnumerableEfCore(data); - mock.ConfigureAsyncEnumerableCalls(enumerable); - mock.As>().ConfigureQueryableCalls(enumerable, data); - mock.As>().Setup(x => x.GetAsyncEnumerator(It.IsAny())).Returns(() => enumerable.GetAsyncEnumerator()); - mock.Setup(m => m.AsQueryable()).Returns(enumerable); + return BuildMockDbSet(data); + } - mock.ConfigureDbSetCalls(data); - return mock; - } + /// + /// See . + /// + /// + /// The type of the entity that the DbSet will represent. + /// + /// + /// The type of the expression visitor that will be used to process LINQ expressions. + /// Can be used to mock EF Core specific expression handling, such as for ILike expressions. + /// + public static Mock> BuildMockDbSet(this IQueryable data) + where TEntity : class + where TExpressionVisitor : ExpressionVisitor, new() + { + var mock = new Mock>(); + var enumerable = new TestAsyncEnumerableEfCore(data); + mock.ConfigureAsyncEnumerableCalls(enumerable); + mock.As>().ConfigureQueryableCalls(enumerable, data); + mock.As>().Setup(x => x.GetAsyncEnumerator(It.IsAny())).Returns(() => enumerable.GetAsyncEnumerator()); + mock.Setup(m => m.AsQueryable()).Returns(enumerable); + + mock.ConfigureDbSetCalls(data); + return mock; + } - private static void ConfigureDbSetCalls(this Mock> mock, IQueryable data) + private static void ConfigureDbSetCalls(this Mock> mock, IQueryable data) where TEntity : class { mock.Setup(m => m.AsQueryable()).Returns(mock.Object); diff --git a/src/MockQueryable/MockQueryable.NSubstitute/MockQueryable.NSubstitute.csproj b/src/MockQueryable/MockQueryable.NSubstitute/MockQueryable.NSubstitute.csproj index 3266042..29fc678 100644 --- a/src/MockQueryable/MockQueryable.NSubstitute/MockQueryable.NSubstitute.csproj +++ b/src/MockQueryable/MockQueryable.NSubstitute/MockQueryable.NSubstitute.csproj @@ -1,7 +1,7 @@  - net6 + net8 MockQueryable.NSubstitute Roman Titov @@ -26,7 +26,7 @@ - + diff --git a/src/MockQueryable/MockQueryable.NSubstitute/NSubstituteExtensions.cs b/src/MockQueryable/MockQueryable.NSubstitute/NSubstituteExtensions.cs index 0db0998..1a2e25e 100644 --- a/src/MockQueryable/MockQueryable.NSubstitute/NSubstituteExtensions.cs +++ b/src/MockQueryable/MockQueryable.NSubstitute/NSubstituteExtensions.cs @@ -1,8 +1,10 @@ using Microsoft.EntityFrameworkCore; +using MockQueryable.Core; using MockQueryable.EntityFrameworkCore; using NSubstitute; using System.Collections.Generic; using System.Linq; +using System.Linq.Expressions; using System.Threading; using System.Threading.Tasks; @@ -10,12 +12,45 @@ namespace MockQueryable.NSubstitute { public static class NSubstituteExtensions { + public static DbSet BuildMockDbSet(this IEnumerable data) + where TEntity : class + where TExpressionVisitor : ExpressionVisitor, new() + => data.BuildMock().BuildMockDbSet(); + public static DbSet BuildMockDbSet(this IEnumerable data) where TEntity : class => data.BuildMock().BuildMockDbSet(); + /// + /// This method allows you to create a mock DbSet for testing purposes. + /// It is particularly useful when you want to simulate the behavior of Entity Framework Core's DbSet + /// with custom expression handling, such as for testing LINQ queries or database operations. + /// The method takes an IQueryable of the entity type and returns a mocked DbSet that implements + /// both IAsyncEnumerable and IQueryable interfaces, allowing for asynchronous enumeration + /// and LINQ query capabilities. + /// + /// + /// The type of the entity that the DbSet will represent. + /// public static DbSet BuildMockDbSet(this IQueryable data) where TEntity : class + { + return BuildMockDbSet(data); + } + + /// + /// See . + /// + /// + /// The type of the entity that the DbSet will represent. + /// + /// + /// The type of the expression visitor that will be used to process LINQ expressions. + /// Can be used to mock EF Core specific expression handling, such as for ILike expressions. + /// + public static DbSet BuildMockDbSet(this IQueryable data) + where TEntity : class + where TExpressionVisitor : ExpressionVisitor, new() { var mock = Substitute.For, IQueryable, IAsyncEnumerable>(); - var enumerable = new TestAsyncEnumerableEfCore(data); + var enumerable = new TestAsyncEnumerableEfCore(data); mock.ConfigureAsyncEnumerableCalls(enumerable); mock.ConfigureQueryableCalls(enumerable, data); @@ -23,13 +58,12 @@ public static DbSet BuildMockDbSet(this IQueryable da if (mock is IAsyncEnumerable asyncEnumerable) { - asyncEnumerable.GetAsyncEnumerator(Arg.Any()).Returns(args => enumerable.GetAsyncEnumerator()); + asyncEnumerable.GetAsyncEnumerator(Arg.Any()).Returns(args => enumerable.GetAsyncEnumerator()); } return mock; } - private static void ConfigureQueryableCalls( this IQueryable mock, IQueryProvider queryProvider, diff --git a/src/MockQueryable/MockQueryable.Sample/MockQueryable.Sample.csproj b/src/MockQueryable/MockQueryable.Sample/MockQueryable.Sample.csproj index 2ebe7d8..60dbdf8 100644 --- a/src/MockQueryable/MockQueryable.Sample/MockQueryable.Sample.csproj +++ b/src/MockQueryable/MockQueryable.Sample/MockQueryable.Sample.csproj @@ -1,18 +1,19 @@  - net6.0 + net8 - - - - + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/src/MockQueryable/MockQueryable.Sample/MyService.cs b/src/MockQueryable/MockQueryable.Sample/MyService.cs index 50d782b..402e08f 100644 --- a/src/MockQueryable/MockQueryable.Sample/MyService.cs +++ b/src/MockQueryable/MockQueryable.Sample/MyService.cs @@ -5,19 +5,25 @@ using AutoMapper; using AutoMapper.QueryableExtensions; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; namespace MockQueryable.Sample { public class MyService { private readonly IUserRepository _userRepository; + private static readonly MapperConfiguration _mapperConfiguration = new( + cfg => + { + cfg.CreateMap() + .ForMember(dto => dto.FirstName, conf => conf.MapFrom(ol => ol.FirstName)) + .ForMember(dto => dto.LastName, conf => conf.MapFrom(ol => ol.LastName)); + }, + loggerFactory: new LoggerFactory()); public static void Initialize() { - Mapper.Initialize(cfg => cfg.CreateMap() - .ForMember(dto => dto.FirstName, conf => conf.MapFrom(ol => ol.FirstName)) - .ForMember(dto => dto.LastName, conf => conf.MapFrom(ol => ol.LastName))); - Mapper.Configuration.AssertConfigurationIsValid(); + _mapperConfiguration.AssertConfigurationIsValid(); } public MyService(IUserRepository userRepository) @@ -68,7 +74,6 @@ public async Task> GetUserReports(DateTime dateFrom, DateTime d }).ToListAsync(); } - public async Task> GetUserReportsAutoMap(DateTime dateFrom, DateTime dateTo) { var query = _userRepository.GetQueryable(); @@ -76,7 +81,7 @@ public async Task> GetUserReportsAutoMap(DateTime dateFrom, Dat query = query.Where(x => x.DateOfBirth >= dateFrom.Date); query = query.Where(x => x.DateOfBirth <= dateTo.Date); - return await query.ProjectTo().ToListAsync(); + return await query.ProjectTo(_mapperConfiguration).ToListAsync(); } } @@ -91,7 +96,6 @@ public interface IUserRepository IAsyncEnumerable GetAllAsync(); } - public class UserReport { public string FirstName { get; set; } diff --git a/src/MockQueryable/MockQueryable.Sample/MyServiceFakeItEasyTests.cs b/src/MockQueryable/MockQueryable.Sample/MyServiceFakeItEasyTests.cs index e74d2ee..039b6ad 100644 --- a/src/MockQueryable/MockQueryable.Sample/MyServiceFakeItEasyTests.cs +++ b/src/MockQueryable/MockQueryable.Sample/MyServiceFakeItEasyTests.cs @@ -14,34 +14,35 @@ namespace MockQueryable.Sample [TestFixture] public class MyServiceFakeItEasyTests { - private static readonly CultureInfo UsCultureInfo = new CultureInfo("en-US"); + private static readonly CultureInfo UsCultureInfo = new("en-US"); [TestCase("AnyFirstName", "AnyExistLastName", "01/20/2012", "Users with DateOfBirth more than limit")] [TestCase("ExistFirstName", "AnyExistLastName", "02/20/2012", "User with FirstName already exist")] [TestCase("AnyFirstName", "ExistLastName", "01/20/2012", "User already exist")] public void CreateUserIfNotExist(string firstName, string lastName, DateTime dateOfBirth, string expectedError) { - //arrange - + // arrange var userRepository = A.Fake(); var service = new MyService(userRepository); var users = new List { - new UserEntity {LastName = "ExistLastName", DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, - new UserEntity {FirstName = "ExistFirstName"}, - new UserEntity {DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, - new UserEntity {DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, - new UserEntity {DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, + new() {LastName = "ExistLastName", DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, + new() {FirstName = "ExistFirstName"}, + new() {DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, + new() {DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, + new() {DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, }; - //expect + + // expect var mock = users.BuildMock(); A.CallTo(() => userRepository.GetQueryable()).Returns(mock); - //act + + // act var ex = Assert.ThrowsAsync(() => service.CreateUserIfNotExist(firstName, lastName, dateOfBirth)); - //assert - Assert.AreEqual(expectedError, ex.Message); + // assert + Assert.That(expectedError, Is.EqualTo(ex.Message)); } [TestCase("01/20/2012", "06/20/2018", 5)] @@ -60,29 +61,28 @@ public async Task GetUserReports(DateTime from, DateTime to, int expectedCount) //act var result = await service.GetUserReports(from, to); //assert - Assert.AreEqual(expectedCount, result.Count); - + Assert.That(expectedCount, Is.EqualTo(result.Count)); } - [TestCase("01/20/2012", "06/20/2018", 5)] [TestCase("01/20/2012", "06/20/2012", 4)] [TestCase("01/20/2012", "02/20/2012", 3)] [TestCase("01/20/2010", "02/20/2011", 0)] public async Task GetUserReports_AutoMap(DateTime from, DateTime to, int expectedCount) { - //arrange + // arrange var userRepository = A.Fake(); var service = new MyService(userRepository); var users = CreateUserList(); - //expect + // expect var mock = users.BuildMock(); A.CallTo(() => userRepository.GetQueryable()).Returns(mock); - //act + + // act var result = await service.GetUserReportsAutoMap(from, to); - //assert - Assert.AreEqual(expectedCount, result.Count); + // assert + Assert.That(expectedCount, Is.EqualTo(result.Count)); } [TestCase("AnyFirstName", "AnyExistLastName", "01/20/2012", "Users with DateOfBirth more than limit")] @@ -90,24 +90,25 @@ public async Task GetUserReports_AutoMap(DateTime from, DateTime to, int expecte [TestCase("AnyFirstName", "ExistLastName", "01/20/2012", "User already exist")] public void DbSetCreateUserIfNotExist(string firstName, string lastName, DateTime dateOfBirth, string expectedError) { - //arrange + // arrange var users = new List { - new UserEntity {LastName = "ExistLastName", DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, - new UserEntity {FirstName = "ExistFirstName"}, - new UserEntity {DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, - new UserEntity {DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, - new UserEntity {DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, + new() {LastName = "ExistLastName", DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, + new() {FirstName = "ExistFirstName"}, + new() {DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, + new() {DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, + new() {DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, }; var mock = users.AsQueryable().BuildMockDbSet(); var userRepository = new TestDbSetRepository(mock); var service = new MyService(userRepository); - //act + + // act var ex = Assert.ThrowsAsync(() => service.CreateUserIfNotExist(firstName, lastName, dateOfBirth)); - //assert - Assert.AreEqual(expectedError, ex.Message); + // assert + Assert.That(expectedError, Is.EqualTo(ex.Message)); } [TestCase("AnyFirstName", "AnyExistLastName", "01/20/2012", "Users with DateOfBirth more than limit")] @@ -115,87 +116,92 @@ public void DbSetCreateUserIfNotExist(string firstName, string lastName, DateTim [TestCase("AnyFirstName", "ExistLastName", "01/20/2012", "User already exist")] public void DbSetCreatedFromCollectionCreateUserIfNotExist(string firstName, string lastName, DateTime dateOfBirth, string expectedError) { - //arrange - var users = new List + // arrange + var users = new List { - new UserEntity {LastName = "ExistLastName", DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, - new UserEntity {FirstName = "ExistFirstName"}, - new UserEntity {DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, - new UserEntity {DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, - new UserEntity {DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, + new() {LastName = "ExistLastName", DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, + new() {FirstName = "ExistFirstName"}, + new() {DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, + new() {DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, + new() {DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, }; - var mock = users.BuildMockDbSet(); - var userRepository = new TestDbSetRepository(mock); - var service = new MyService(userRepository); - //act - var ex = Assert.ThrowsAsync(() => - service.CreateUserIfNotExist(firstName, lastName, dateOfBirth)); - //assert - Assert.AreEqual(expectedError, ex.Message); - + var mock = users.BuildMockDbSet(); + var userRepository = new TestDbSetRepository(mock); + var service = new MyService(userRepository); + // act + var ex = Assert.ThrowsAsync(() => + service.CreateUserIfNotExist(firstName, lastName, dateOfBirth)); + // assert + Assert.That(expectedError, Is.EqualTo(ex.Message)); } - [TestCase("AnyFirstName", "ExistLastName", "01/20/2012")] + [TestCase("AnyFirstName", "ExistLastName", "01/20/2012")] public async Task DbSetCreateUser(string firstName, string lastName, DateTime dateOfBirth) { - //arrange + // arrange var userEntities = new List(); var mock = userEntities.AsQueryable().BuildMockDbSet(); A.CallTo(() => mock.AddAsync(A._, A._)) .ReturnsLazily(call => { - userEntities.Add((UserEntity) call.Arguments[0]); + userEntities.Add((UserEntity)call.Arguments[0]); return default; }); var userRepository = new TestDbSetRepository(mock); var service = new MyService(userRepository); - //act + + // act await service.CreateUserIfNotExist(firstName, lastName, dateOfBirth); + // assert var entity = mock.Single(); - Assert.AreEqual(firstName, entity.FirstName); - Assert.AreEqual(lastName, entity.LastName); - Assert.AreEqual(dateOfBirth, entity.DateOfBirth); + Assert.That(firstName, Is.EqualTo(entity.FirstName)); + Assert.That(lastName, Is.EqualTo(entity.LastName)); + Assert.That(dateOfBirth, Is.EqualTo(entity.DateOfBirth)); } [TestCase("AnyFirstName", "ExistLastName", "01/20/2012")] public async Task DbSetCreatedFromCollectionCreateUser1(string firstName, string lastName, DateTime dateOfBirth) { - //arrange - var userEntities = new List(); - var mock = userEntities.BuildMockDbSet(); - A.CallTo(() => mock.AddAsync(A._, A._)) - .ReturnsLazily(call => - { - userEntities.Add((UserEntity)call.Arguments[0]); - return default; - }); - var userRepository = new TestDbSetRepository(mock); - var service = new MyService(userRepository); - //act - await service.CreateUserIfNotExist(firstName, lastName, dateOfBirth); - // assert - var entity = mock.Single(); - Assert.AreEqual(firstName, entity.FirstName); - Assert.AreEqual(lastName, entity.LastName); - Assert.AreEqual(dateOfBirth, entity.DateOfBirth); + // arrange + var userEntities = new List(); + var mock = userEntities.BuildMockDbSet(); + A.CallTo(() => mock.AddAsync(A._, A._)) + .ReturnsLazily(call => + { + userEntities.Add((UserEntity)call.Arguments[0]); + return default; + }); + var userRepository = new TestDbSetRepository(mock); + var service = new MyService(userRepository); + + // act + await service.CreateUserIfNotExist(firstName, lastName, dateOfBirth); + + // assert + var entity = mock.Single(); + Assert.That(firstName, Is.EqualTo(entity.FirstName)); + Assert.That(lastName, Is.EqualTo(entity.LastName)); + Assert.That(dateOfBirth, Is.EqualTo(entity.DateOfBirth)); } - [TestCase("01/20/2012", "06/20/2018", 5)] + [TestCase("01/20/2012", "06/20/2018", 5)] [TestCase("01/20/2012", "06/20/2012", 4)] [TestCase("01/20/2012", "02/20/2012", 3)] [TestCase("01/20/2010", "02/20/2011", 0)] public async Task DbSetGetUserReports(DateTime from, DateTime to, int expectedCount) { - //arrange + // arrange var users = CreateUserList(); var mock = users.AsQueryable().BuildMockDbSet(); var userRepository = new TestDbSetRepository(mock); var service = new MyService(userRepository); - //act + + // act var result = await service.GetUserReports(from, to); - //assert - Assert.AreEqual(expectedCount, result.Count); + + // assert + Assert.That(expectedCount, Is.EqualTo(result.Count)); } [TestCase("01/20/2012", "06/20/2018", 5)] @@ -204,18 +210,20 @@ public async Task DbSetGetUserReports(DateTime from, DateTime to, int expectedCo [TestCase("01/20/2010", "02/20/2011", 0)] public async Task DbSetCreatedFromCollectionGetUserReports(DateTime from, DateTime to, int expectedCount) { - //arrange - var users = CreateUserList(); - var mock = users.BuildMockDbSet(); - var userRepository = new TestDbSetRepository(mock); - var service = new MyService(userRepository); - //act - var result = await service.GetUserReports(from, to); - //assert - Assert.AreEqual(expectedCount, result.Count); + // arrange + var users = CreateUserList(); + var mock = users.BuildMockDbSet(); + var userRepository = new TestDbSetRepository(mock); + var service = new MyService(userRepository); + + // act + var result = await service.GetUserReports(from, to); + + // assert + Assert.That(expectedCount, Is.EqualTo(result.Count)); } - [TestCase] + [TestCase] public async Task DbSetGetAllUserEntitiesAsync() { // arrange @@ -228,23 +236,23 @@ public async Task DbSetGetAllUserEntitiesAsync() var result = await userRepository.GetAllAsync().ToListAsync(); // assert - Assert.AreEqual(users.Count, result.Count); + Assert.That(users.Count, Is.EqualTo(result.Count)); } [TestCase] public async Task DbSetCreatedFromCollectionGetAllUserEntitiesAsync() { - // arrange - var users = CreateUserList(); + // arrange + var users = CreateUserList(); - var mockDbSet = users.BuildMockDbSet(); - var userRepository = new TestDbSetRepository(mockDbSet); + var mockDbSet = users.BuildMockDbSet(); + var userRepository = new TestDbSetRepository(mockDbSet); - // act - var result = await userRepository.GetAllAsync().ToListAsync(); + // act + var result = await userRepository.GetAllAsync().ToListAsync(); - // assert - Assert.AreEqual(users.Count, result.Count); + // assert + Assert.That(users.Count, Is.EqualTo(result.Count)); } [TestCase] @@ -254,44 +262,85 @@ public async Task DbSetToListAsyncAsync_ShouldReturnAllEntities_WhenSourceIsChan var users = new List(); var mockDbSet = users.AsQueryable().BuildMockDbSet(); - + // act var result1 = await mockDbSet.ToListAsync(); users.AddRange(CreateUserList()); var result2 = await mockDbSet.ToListAsync(); // assert - Assert.AreEqual(0, result1.Count); - Assert.AreEqual(users.Count, result2.Count); + Assert.That(0, Is.EqualTo(result1.Count)); + Assert.That(users.Count, Is.EqualTo(result2.Count)); } [TestCase] public async Task DbSetGetAllUserEntity() { - //arrange - var users = CreateUserList(); - var mock = users.AsQueryable().BuildMockDbSet(); - var userRepository = new TestDbSetRepository(mock); - //act - var result = await userRepository.GetAll(); - //assert - Assert.AreEqual(users.Count, result.Count); + //arrange + var users = CreateUserList(); + var mock = users.AsQueryable().BuildMockDbSet(); + var userRepository = new TestDbSetRepository(mock); + + //act + var result = await userRepository.GetAll(); + + //assert + Assert.That(users.Count, Is.EqualTo(result.Count)); } [TestCase] public async Task DbSetCreatedFromCollectionGetAllUserEntity() { - //arrange - var users = CreateUserList(); - var mock = users.BuildMockDbSet(); - var userRepository = new TestDbSetRepository(mock); - //act - var result = await userRepository.GetAll(); - //assert - Assert.AreEqual(users.Count, result.Count); + // arrange + var users = CreateUserList(); + var mock = users.BuildMockDbSet(); + var userRepository = new TestDbSetRepository(mock); + + // act + var result = await userRepository.GetAll(); + + // assert + Assert.That(users.Count, Is.EqualTo(result.Count)); + } + + [TestCase] + public void GetUsersByFirstName_ExpressionVisitorMissing_ThrowsException() + { + // arrange + var users = CreateUserList(); + + var mockDbSet = users.AsQueryable().BuildMockDbSet(); + var userRepository = new TestDbSetRepository(mockDbSet); + + // act + var exception = Assert.ThrowsAsync(() => userRepository.GetUsersByFirstName("naME")); + + // assert + Assert.That( + exception.Message, + Is.EqualTo( + "The 'ILike' method is not supported because the query has switched to client-evaluation. " + + "This usually happens when the arguments to the method cannot be translated to server. " + + "Rewrite the query to avoid client evaluation of arguments so that method can be translated to server.")); } - private static List CreateUserList() => new List + [TestCase] + public async Task GetUsersByFirstName_PartOfNameCaseInsensitiveSearch_AllMatchesReturned() + { + // arrange + var users = CreateUserList(); + + var mockDbSet = users.AsQueryable().BuildMockDbSet(); + var userRepository = new TestDbSetRepository(mockDbSet); + + // act + var result = await userRepository.GetUsersByFirstName("naME"); + + // assert + Assert.That(users.Count, Is.EqualTo(result.Count())); + } + + private static List CreateUserList() => new() { new UserEntity { @@ -319,7 +368,5 @@ public async Task DbSetCreatedFromCollectionGetAllUserEntity() DateOfBirth = DateTime.Parse("01/20/2018", UsCultureInfo.DateTimeFormat) }, }; - - } } diff --git a/src/MockQueryable/MockQueryable.Sample/MyServiceMoqTests.cs b/src/MockQueryable/MockQueryable.Sample/MyServiceMoqTests.cs index c7cec20..99da01d 100644 --- a/src/MockQueryable/MockQueryable.Sample/MyServiceMoqTests.cs +++ b/src/MockQueryable/MockQueryable.Sample/MyServiceMoqTests.cs @@ -11,10 +11,10 @@ namespace MockQueryable.Sample { - [TestFixture] + [TestFixture] public class MyServiceMoqTests { - private static readonly CultureInfo UsCultureInfo = new CultureInfo("en-US"); + private static readonly CultureInfo UsCultureInfo = new("en-US"); [TestCase("AnyFirstName", "AnyExistLastName", "01/20/2012", "Users with DateOfBirth more than limit")] [TestCase("ExistFirstName", "AnyExistLastName", "02/20/2012", "User with FirstName already exist")] @@ -26,11 +26,11 @@ public void CreateUserIfNotExist(string firstName, string lastName, DateTime dat var service = new MyService(userRepository.Object); var users = new List { - new UserEntity {LastName = "ExistLastName", DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, - new UserEntity {FirstName = "ExistFirstName"}, - new UserEntity {DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, - new UserEntity {DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, - new UserEntity {DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)} + new() {LastName = "ExistLastName", DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, + new() {FirstName = "ExistFirstName"}, + new() {DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, + new() {DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, + new() {DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)} }; //expect var mock = users.BuildMock(); @@ -39,7 +39,7 @@ public void CreateUserIfNotExist(string firstName, string lastName, DateTime dat var ex = Assert.ThrowsAsync(() => service.CreateUserIfNotExist(firstName, lastName, dateOfBirth)); //assert - Assert.AreEqual(expectedError, ex.Message); + Assert.That(expectedError, Is.EqualTo(ex.Message)); } [TestCase("01/20/2012", "06/20/2018", 5)] @@ -58,11 +58,9 @@ public async Task GetUserReports(DateTime from, DateTime to, int expectedCount) //act var result = await service.GetUserReports(from, to); //assert - Assert.AreEqual(expectedCount, result.Count); + Assert.That(expectedCount, Is.EqualTo(result.Count)); } - - [TestCase("01/20/2012", "06/20/2018", 5)] [TestCase("01/20/2012", "06/20/2012", 4)] [TestCase("01/20/2012", "02/20/2012", 3)] @@ -79,10 +77,9 @@ public async Task GetUserReports_AutoMap(DateTime from, DateTime to, int expecte //act var result = await service.GetUserReportsAutoMap(from, to); //assert - Assert.AreEqual(expectedCount, result.Count); + Assert.That(expectedCount, Is.EqualTo(result.Count)); } - [TestCase("AnyFirstName", "AnyExistLastName", "01/20/2012", "Users with DateOfBirth more than limit")] [TestCase("ExistFirstName", "AnyExistLastName", "02/20/2012", "User with FirstName already exist")] [TestCase("AnyFirstName", "ExistLastName", "01/20/2012", "User already exist")] @@ -91,11 +88,11 @@ public void DbSetCreateUserIfNotExist(string firstName, string lastName, DateTim //arrange var users = new List { - new UserEntity {LastName = "ExistLastName", DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, - new UserEntity {FirstName = "ExistFirstName"}, - new UserEntity {DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, - new UserEntity {DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, - new UserEntity {DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)} + new() {LastName = "ExistLastName", DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, + new() {FirstName = "ExistFirstName"}, + new() {DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, + new() {DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, + new() {DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)} }; var mock = users.AsQueryable().BuildMockDbSet(); var userRepository = new TestDbSetRepository(mock.Object); @@ -104,7 +101,7 @@ public void DbSetCreateUserIfNotExist(string firstName, string lastName, DateTim var ex = Assert.ThrowsAsync(() => service.CreateUserIfNotExist(firstName, lastName, dateOfBirth)); //assert - Assert.AreEqual(expectedError, ex.Message); + Assert.That(expectedError, Is.EqualTo(ex.Message)); } [TestCase("AnyFirstName", "AnyExistLastName", "01/20/2012", "Users with DateOfBirth more than limit")] @@ -112,26 +109,26 @@ public void DbSetCreateUserIfNotExist(string firstName, string lastName, DateTim [TestCase("AnyFirstName", "ExistLastName", "01/20/2012", "User already exist")] public void DbSetCreatedFromCollectionCreateUserIfNotExist(string firstName, string lastName, DateTime dateOfBirth, string expectedError) { - //arrange - var users = new List + //arrange + var users = new List { - new UserEntity {LastName = "ExistLastName", DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, - new UserEntity {FirstName = "ExistFirstName"}, - new UserEntity {DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, - new UserEntity {DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, - new UserEntity {DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)} + new() {LastName = "ExistLastName", DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, + new() {FirstName = "ExistFirstName"}, + new() {DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, + new() {DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)}, + new() {DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat)} }; - var mock = users.BuildMockDbSet(); - var userRepository = new TestDbSetRepository(mock.Object); - var service = new MyService(userRepository); - //act - var ex = Assert.ThrowsAsync(() => - service.CreateUserIfNotExist(firstName, lastName, dateOfBirth)); - //assert - Assert.AreEqual(expectedError, ex.Message); + var mock = users.BuildMockDbSet(); + var userRepository = new TestDbSetRepository(mock.Object); + var service = new MyService(userRepository); + //act + var ex = Assert.ThrowsAsync(() => + service.CreateUserIfNotExist(firstName, lastName, dateOfBirth)); + //assert + Assert.That(expectedError, Is.EqualTo(ex.Message)); } - [TestCase("AnyFirstName", "ExistLastName", "01/20/2012")] + [TestCase("AnyFirstName", "ExistLastName", "01/20/2012")] public async Task DbSetCreateUser(string firstName, string lastName, DateTime dateOfBirth) { //arrange @@ -140,38 +137,38 @@ public async Task DbSetCreateUser(string firstName, string lastName, DateTime da mock.Setup(set => set.AddAsync(It.IsAny(), It.IsAny())) .Callback((UserEntity entity, CancellationToken _) => userEntities.Add(entity)); - var userRepository = new TestDbSetRepository(mock.Object); + var userRepository = new TestDbSetRepository(mock.Object); var service = new MyService(userRepository); //act await service.CreateUserIfNotExist(firstName, lastName, dateOfBirth); // assert var entity = mock.Object.Single(); - Assert.AreEqual(firstName, entity.FirstName); - Assert.AreEqual(lastName, entity.LastName); - Assert.AreEqual(dateOfBirth, entity.DateOfBirth); + Assert.That(firstName, Is.EqualTo(entity.FirstName)); + Assert.That(lastName, Is.EqualTo(entity.LastName)); + Assert.That(dateOfBirth, Is.EqualTo(entity.DateOfBirth)); } [TestCase("AnyFirstName", "ExistLastName", "01/20/2012")] public async Task DbSetCreatedFromCollectionCreateUser(string firstName, string lastName, DateTime dateOfBirth) { - //arrange - var userEntities = new List(); - var mock = userEntities.BuildMockDbSet(); - - mock.Setup(set => set.AddAsync(It.IsAny(), It.IsAny())) - .Callback((UserEntity entity, CancellationToken _) => userEntities.Add(entity)); - var userRepository = new TestDbSetRepository(mock.Object); - var service = new MyService(userRepository); - //act - await service.CreateUserIfNotExist(firstName, lastName, dateOfBirth); - // assert - var entity = mock.Object.Single(); - Assert.AreEqual(firstName, entity.FirstName); - Assert.AreEqual(lastName, entity.LastName); - Assert.AreEqual(dateOfBirth, entity.DateOfBirth); + //arrange + var userEntities = new List(); + var mock = userEntities.BuildMockDbSet(); + + mock.Setup(set => set.AddAsync(It.IsAny(), It.IsAny())) + .Callback((UserEntity entity, CancellationToken _) => userEntities.Add(entity)); + var userRepository = new TestDbSetRepository(mock.Object); + var service = new MyService(userRepository); + //act + await service.CreateUserIfNotExist(firstName, lastName, dateOfBirth); + // assert + var entity = mock.Object.Single(); + Assert.That(firstName, Is.EqualTo(entity.FirstName)); + Assert.That(lastName, Is.EqualTo(entity.LastName)); + Assert.That(dateOfBirth, Is.EqualTo(entity.DateOfBirth)); } - [TestCase("01/20/2012", "06/20/2018", 5)] + [TestCase("01/20/2012", "06/20/2018", 5)] [TestCase("01/20/2012", "06/20/2012", 4)] [TestCase("01/20/2012", "02/20/2012", 3)] [TestCase("01/20/2010", "02/20/2011", 0)] @@ -185,7 +182,7 @@ public async Task DbSetGetUserReports(DateTime from, DateTime to, int expectedCo //act var result = await service.GetUserReports(from, to); //assert - Assert.AreEqual(expectedCount, result.Count); + Assert.That(expectedCount, Is.EqualTo(result.Count)); } [TestCase("01/20/2012", "06/20/2018", 5)] @@ -194,18 +191,18 @@ public async Task DbSetGetUserReports(DateTime from, DateTime to, int expectedCo [TestCase("01/20/2010", "02/20/2011", 0)] public async Task DbSetCreatedFromCollectionGetUserReports(DateTime from, DateTime to, int expectedCount) { - //arrange - var users = CreateUserList(); - var mock = users.BuildMockDbSet(); - var userRepository = new TestDbSetRepository(mock.Object); - var service = new MyService(userRepository); - //act - var result = await service.GetUserReports(from, to); - //assert - Assert.AreEqual(expectedCount, result.Count); + //arrange + var users = CreateUserList(); + var mock = users.BuildMockDbSet(); + var userRepository = new TestDbSetRepository(mock.Object); + var service = new MyService(userRepository); + //act + var result = await service.GetUserReports(from, to); + //assert + Assert.That(expectedCount, Is.EqualTo(result.Count)); } - [TestCase] + [TestCase] public async Task DbSetGetAllUserEntity() { //arrange @@ -215,55 +212,50 @@ public async Task DbSetGetAllUserEntity() //act var result = await userRepository.GetAll(); //assert - Assert.AreEqual(users.Count, result.Count); + Assert.That(users.Count, Is.EqualTo(result.Count)); } [TestCase] public async Task DbSetCreatedFromCollectionGetAllUserEntity() { - //arrange - var users = CreateUserList(); - var mock = users.BuildMockDbSet(); - var userRepository = new TestDbSetRepository(mock.Object); - //act - var result = await userRepository.GetAll(); - //assert - Assert.AreEqual(users.Count, result.Count); + //arrange + var users = CreateUserList(); + var mock = users.BuildMockDbSet(); + var userRepository = new TestDbSetRepository(mock.Object); + //act + var result = await userRepository.GetAll(); + //assert + Assert.That(users.Count, Is.EqualTo(result.Count)); } - [TestCase] + [TestCase] public async Task DbSetFindAsyncUserEntity() { //arrange var userId = Guid.NewGuid(); var users = new List { - new UserEntity - { + new() { Id = Guid.NewGuid(), FirstName = "FirstName1", LastName = "LastName", DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat) }, - new UserEntity - { + new() { Id = Guid.NewGuid(), FirstName = "FirstName2", LastName = "LastName", DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat) }, - new UserEntity - { + new() { Id = userId, FirstName = "FirstName3", LastName = "LastName", DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat) }, - new UserEntity - { + new() { Id = Guid.NewGuid(), FirstName = "FirstName3", LastName = "LastName", DateOfBirth = DateTime.Parse("03/20/2012", UsCultureInfo.DateTimeFormat) }, - new UserEntity - { + new() { Id = Guid.NewGuid(), FirstName = "FirstName5", LastName = "LastName", DateOfBirth = DateTime.Parse("01/20/2018", UsCultureInfo.DateTimeFormat) @@ -273,7 +265,7 @@ public async Task DbSetFindAsyncUserEntity() var mock = users.AsQueryable().BuildMockDbSet(); mock.Setup(x => x.FindAsync(It.IsAny())).ReturnsAsync((object[] ids) => { - var id = (Guid) ids.First(); + var id = (Guid)ids.First(); return users.FirstOrDefault(x => x.Id == id); }); var userRepository = new TestDbSetRepository(mock.Object); @@ -282,67 +274,61 @@ public async Task DbSetFindAsyncUserEntity() var result = await ((DbSet)userRepository.GetQueryable()).FindAsync(userId); //assert - Assert.IsNotNull(result); - Assert.AreEqual("FirstName3", result.FirstName); + Assert.That(result, Is.Not.Null); + Assert.That("FirstName3", Is.EqualTo(result.FirstName)); } - [TestCase] public async Task DbSetCreatedFromCollectionFindAsyncUserEntity() { - //arrange - var userId = Guid.NewGuid(); - var users = new List + //arrange + var userId = Guid.NewGuid(); + var users = new List { - new UserEntity - { + new() { Id = Guid.NewGuid(), FirstName = "FirstName1", LastName = "LastName", DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat) }, - new UserEntity - { + new() { Id = Guid.NewGuid(), FirstName = "FirstName2", LastName = "LastName", DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat) }, - new UserEntity - { + new() { Id = userId, FirstName = "FirstName3", LastName = "LastName", DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat) }, - new UserEntity - { + new() { Id = Guid.NewGuid(), FirstName = "FirstName3", LastName = "LastName", DateOfBirth = DateTime.Parse("03/20/2012", UsCultureInfo.DateTimeFormat) }, - new UserEntity - { + new() { Id = Guid.NewGuid(), FirstName = "FirstName5", LastName = "LastName", DateOfBirth = DateTime.Parse("01/20/2018", UsCultureInfo.DateTimeFormat) } }; - var mock = users.BuildMockDbSet(); - mock.Setup(x => x.FindAsync(It.IsAny())).ReturnsAsync((object[] ids) => - { - var id = (Guid)ids.First(); - return users.FirstOrDefault(x => x.Id == id); - }); - var userRepository = new TestDbSetRepository(mock.Object); + var mock = users.BuildMockDbSet(); + mock.Setup(x => x.FindAsync(It.IsAny())).ReturnsAsync((object[] ids) => + { + var id = (Guid)ids.First(); + return users.FirstOrDefault(x => x.Id == id); + }); + var userRepository = new TestDbSetRepository(mock.Object); - //act - var result = await ((DbSet)userRepository.GetQueryable()).FindAsync(userId); + //act + var result = await ((DbSet)userRepository.GetQueryable()).FindAsync(userId); - //assert - Assert.IsNotNull(result); - Assert.AreEqual("FirstName3", result.FirstName); + //assert + Assert.That(result, Is.Not.Null); + Assert.That("FirstName3", Is.EqualTo(result.FirstName)); } - [TestCase] + [TestCase] public async Task DbSetGetAllUserEntitiesAsync() { // arrange @@ -355,10 +341,9 @@ public async Task DbSetGetAllUserEntitiesAsync() var result = await userRepository.GetAllAsync().ToListAsync(); // assert - Assert.AreEqual(users.Count, result.Count); + Assert.That(users.Count, Is.EqualTo(result.Count)); } - - + [TestCase] public async Task DbSetToListAsyncAsync_ShouldReturnAllEntities_WhenSourceIsChanged() { @@ -373,29 +358,64 @@ public async Task DbSetToListAsyncAsync_ShouldReturnAllEntities_WhenSourceIsChan var result2 = await mockDbSet.Object.ToListAsync(); // assert - Assert.AreEqual(0, result1.Count); - Assert.AreEqual(users.Count, result2.Count); + Assert.That(0, Is.EqualTo(result1.Count)); + Assert.That(users.Count, Is.EqualTo(result2.Count)); } + [TestCase] + public async Task DbSetCreatedFromCollectionGetAllUserEntitiesAsync() + { + // arrange + var users = CreateUserList(); + + var mockDbSet = users.BuildMockDbSet(); + var userRepository = new TestDbSetRepository(mockDbSet.Object); + // act + var result = await userRepository.GetAllAsync().ToListAsync(); + + // assert + Assert.That(users.Count, Is.EqualTo(result.Count)); + } [TestCase] - public async Task DbSetCreatedFromCollectionGetAllUserEntitiesAsync() + public void GetUsersByFirstName_ExpressionVisitorMissing_ThrowsException() + { + // arrange + var users = CreateUserList(); + + var mockDbSet = users.AsQueryable().BuildMockDbSet(); + var userRepository = new TestDbSetRepository(mockDbSet.Object); + + // act + var exception = Assert.ThrowsAsync(() => userRepository.GetUsersByFirstName("naME")); + + // assert + Assert.That( + exception.Message, + Is.EqualTo( + "The 'ILike' method is not supported because the query has switched to client-evaluation. " + + "This usually happens when the arguments to the method cannot be translated to server. " + + "Rewrite the query to avoid client evaluation of arguments so that method can be translated to server.")); + } + + [TestCase] + public async Task GetUsersByFirstName_PartOfNameCaseInsensitiveSearch_AllMatchesReturned() { - // arrange - var users = CreateUserList(); + // arrange + var users = CreateUserList(); - var mockDbSet = users.BuildMockDbSet(); - var userRepository = new TestDbSetRepository(mockDbSet.Object); + var mockDbSet = users.AsQueryable().BuildMockDbSet(); + var userRepository = new TestDbSetRepository(mockDbSet.Object); - // act - var result = await userRepository.GetAllAsync().ToListAsync(); + // act + var result = await userRepository.GetUsersByFirstName("naME"); - // assert - Assert.AreEqual(users.Count, result.Count); + // assert + Assert.That(users.Count, Is.EqualTo(result.Count())); } - private static List CreateUserList() => new List + private static List CreateUserList() => new() { new UserEntity { FirstName = "FirstName1", LastName = "LastName", DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat) }, new UserEntity { FirstName = "FirstName2", LastName = "LastName", DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat) }, diff --git a/src/MockQueryable/MockQueryable.Sample/MyServiceNSubstituteTests.cs b/src/MockQueryable/MockQueryable.Sample/MyServiceNSubstituteTests.cs index 1f9e08c..b9b8509 100644 --- a/src/MockQueryable/MockQueryable.Sample/MyServiceNSubstituteTests.cs +++ b/src/MockQueryable/MockQueryable.Sample/MyServiceNSubstituteTests.cs @@ -9,336 +9,365 @@ namespace MockQueryable.Sample { - [TestFixture] - public class MyServiceNSubstituteTests + [TestFixture] + public class MyServiceNSubstituteTests + { + private static readonly CultureInfo UsCultureInfo = new("en-US"); + + [TestCase("AnyFirstName", "AnyExistLastName", "01/20/2012", "Users with DateOfBirth more than limit")] + [TestCase("ExistFirstName", "AnyExistLastName", "02/20/2012", "User with FirstName already exist")] + [TestCase("AnyFirstName", "ExistLastName", "01/20/2012", "User already exist")] + public void CreateUserIfNotExist(string firstName, string lastName, DateTime dateOfBirth, string expectedError) { - private static readonly CultureInfo UsCultureInfo = new CultureInfo("en-US"); - - - [TestCase("AnyFirstName", "AnyExistLastName", "01/20/2012", "Users with DateOfBirth more than limit")] - [TestCase("ExistFirstName", "AnyExistLastName", "02/20/2012", "User with FirstName already exist")] - [TestCase("AnyFirstName", "ExistLastName", "01/20/2012", "User already exist")] - public void CreateUserIfNotExist(string firstName, string lastName, DateTime dateOfBirth, string expectedError) - { - //arrange - var userRepository = Substitute.For(); - var service = new MyService(userRepository); - var users = new List - { - new UserEntity{LastName = "ExistLastName", DateOfBirth = DateTime.Parse("01/20/2012",UsCultureInfo.DateTimeFormat)}, - new UserEntity{FirstName = "ExistFirstName"}, - new UserEntity{DateOfBirth = DateTime.Parse("01/20/2012",UsCultureInfo.DateTimeFormat)}, - new UserEntity{DateOfBirth = DateTime.Parse("01/20/2012",UsCultureInfo.DateTimeFormat)}, - new UserEntity{DateOfBirth = DateTime.Parse("01/20/2012",UsCultureInfo.DateTimeFormat)}, - }; - //expect - var mock = users.BuildMock(); - userRepository.GetQueryable().Returns(mock); - //act - var ex= Assert.ThrowsAsync(() => service.CreateUserIfNotExist(firstName, lastName, dateOfBirth)); - //assert - Assert.AreEqual(expectedError, ex.Message); - - } - - [TestCase("01/20/2012", "06/20/2018",5)] - [TestCase("01/20/2012", "06/20/2012",4)] - [TestCase("01/20/2012", "02/20/2012",3)] - [TestCase("01/20/2010", "02/20/2011",0)] - public async Task GetUserReports(DateTime from, DateTime to, int expectedCount) - { - //arrange - var userRepository = Substitute.For(); - var service = new MyService(userRepository); - List users = CreateUserList(); - - //expect - var mock = users.BuildMock(); - userRepository.GetQueryable().Returns(mock); - //act - var result = await service.GetUserReports(from, to); - //assert - Assert.AreEqual(expectedCount, result.Count); - } - - [TestCase("01/20/2012", "06/20/2018", 5)] - [TestCase("01/20/2012", "06/20/2012", 4)] - [TestCase("01/20/2012", "02/20/2012", 3)] - [TestCase("01/20/2010", "02/20/2011", 0)] - public async Task GetUserReports_AutoMap(DateTime from, DateTime to, int expectedCount) - { - //arrange - List users = CreateUserList(); - - var mock = users.AsQueryable().BuildMockDbSet(); - var userRepository = new TestDbSetRepository(mock); - var service = new MyService(userRepository); - //act - var result = await service.GetUserReportsAutoMap(from, to); - //assert - Assert.AreEqual(expectedCount, result.Count); - - } - - [TestCase("01/20/2012", "06/20/2018", 5)] - [TestCase("01/20/2012", "06/20/2012", 4)] - [TestCase("01/20/2012", "02/20/2012", 3)] - [TestCase("01/20/2010", "02/20/2011", 0)] - public async Task GetUserReports_AutoMap_FromDbSetCreatedFromCollection(DateTime from, DateTime to, int expectedCount) - { - //arrange - List users = CreateUserList(); - - var mock = users.BuildMockDbSet(); - var userRepository = new TestDbSetRepository(mock); - var service = new MyService(userRepository); - //act - var result = await service.GetUserReportsAutoMap(from, to); - //assert - Assert.AreEqual(expectedCount, result.Count); - - } - - [TestCase("AnyFirstName", "AnyExistLastName", "01/20/2012", "Users with DateOfBirth more than limit")] - [TestCase("ExistFirstName", "AnyExistLastName", "02/20/2012", "User with FirstName already exist")] - [TestCase("AnyFirstName", "ExistLastName", "01/20/2012", "User already exist")] - public void DbSetCreateUserIfNotExist(string firstName, string lastName, DateTime dateOfBirth, string expectedError) - { - //arrange - var users = new List - { - new UserEntity{LastName = "ExistLastName", DateOfBirth = DateTime.Parse("01/20/2012",UsCultureInfo.DateTimeFormat)}, - new UserEntity{FirstName = "ExistFirstName"}, - new UserEntity{DateOfBirth = DateTime.Parse("01/20/2012",UsCultureInfo.DateTimeFormat)}, - new UserEntity{DateOfBirth = DateTime.Parse("01/20/2012",UsCultureInfo.DateTimeFormat)}, - new UserEntity{DateOfBirth = DateTime.Parse("01/20/2012",UsCultureInfo.DateTimeFormat)}, - }; - var mock = users.AsQueryable().BuildMockDbSet(); - var userRepository = new TestDbSetRepository(mock); - var service = new MyService(userRepository); - //act - var ex = Assert.ThrowsAsync(() => service.CreateUserIfNotExist(firstName, lastName, dateOfBirth)); - //assert - Assert.AreEqual(expectedError, ex.Message); + //arrange + var userRepository = Substitute.For(); + var service = new MyService(userRepository); + var users = new List + { + new() {LastName = "ExistLastName", DateOfBirth = DateTime.Parse("01/20/2012",UsCultureInfo.DateTimeFormat)}, + new() {FirstName = "ExistFirstName"}, + new() {DateOfBirth = DateTime.Parse("01/20/2012",UsCultureInfo.DateTimeFormat)}, + new() {DateOfBirth = DateTime.Parse("01/20/2012",UsCultureInfo.DateTimeFormat)}, + new() {DateOfBirth = DateTime.Parse("01/20/2012",UsCultureInfo.DateTimeFormat)}, + }; + //expect + var mock = users.BuildMock(); + userRepository.GetQueryable().Returns(mock); + //act + var ex = Assert.ThrowsAsync(() => service.CreateUserIfNotExist(firstName, lastName, dateOfBirth)); + //assert + Assert.That(expectedError, Is.EqualTo(ex.Message)); + } - } + [TestCase("01/20/2012", "06/20/2018", 5)] + [TestCase("01/20/2012", "06/20/2012", 4)] + [TestCase("01/20/2012", "02/20/2012", 3)] + [TestCase("01/20/2010", "02/20/2011", 0)] + public async Task GetUserReports(DateTime from, DateTime to, int expectedCount) + { + //arrange + var userRepository = Substitute.For(); + var service = new MyService(userRepository); + List users = CreateUserList(); + + //expect + var mock = users.BuildMock(); + userRepository.GetQueryable().Returns(mock); + //act + var result = await service.GetUserReports(from, to); + //assert + Assert.That(expectedCount, Is.EqualTo(result.Count)); + } + [TestCase("01/20/2012", "06/20/2018", 5)] + [TestCase("01/20/2012", "06/20/2012", 4)] + [TestCase("01/20/2012", "02/20/2012", 3)] + [TestCase("01/20/2010", "02/20/2011", 0)] + public async Task GetUserReports_AutoMap(DateTime from, DateTime to, int expectedCount) + { + //arrange + List users = CreateUserList(); + + var mock = users.AsQueryable().BuildMockDbSet(); + var userRepository = new TestDbSetRepository(mock); + var service = new MyService(userRepository); + //act + var result = await service.GetUserReportsAutoMap(from, to); + //assert + Assert.That(expectedCount, Is.EqualTo(result.Count)); + } - [TestCase("AnyFirstName", "AnyExistLastName", "01/20/2012", "Users with DateOfBirth more than limit")] - [TestCase("ExistFirstName", "AnyExistLastName", "02/20/2012", "User with FirstName already exist")] - [TestCase("AnyFirstName", "ExistLastName", "01/20/2012", "User already exist")] - public void DbSetCreatedFromCollectionCreateUserIfNotExist(string firstName, string lastName, DateTime dateOfBirth, string expectedError) - { - //arrange - var users = new List + [TestCase("01/20/2012", "06/20/2018", 5)] + [TestCase("01/20/2012", "06/20/2012", 4)] + [TestCase("01/20/2012", "02/20/2012", 3)] + [TestCase("01/20/2010", "02/20/2011", 0)] + public async Task GetUserReports_AutoMap_FromDbSetCreatedFromCollection(DateTime from, DateTime to, int expectedCount) + { + //arrange + List users = CreateUserList(); + + var mock = users.BuildMockDbSet(); + var userRepository = new TestDbSetRepository(mock); + var service = new MyService(userRepository); + //act + var result = await service.GetUserReportsAutoMap(from, to); + //assert + Assert.That(expectedCount, Is.EqualTo(result.Count)); + } + + [TestCase("AnyFirstName", "AnyExistLastName", "01/20/2012", "Users with DateOfBirth more than limit")] + [TestCase("ExistFirstName", "AnyExistLastName", "02/20/2012", "User with FirstName already exist")] + [TestCase("AnyFirstName", "ExistLastName", "01/20/2012", "User already exist")] + public void DbSetCreateUserIfNotExist(string firstName, string lastName, DateTime dateOfBirth, string expectedError) + { + //arrange + var users = new List { - new UserEntity{LastName = "ExistLastName", DateOfBirth = DateTime.Parse("01/20/2012",UsCultureInfo.DateTimeFormat)}, - new UserEntity{FirstName = "ExistFirstName"}, - new UserEntity{DateOfBirth = DateTime.Parse("01/20/2012",UsCultureInfo.DateTimeFormat)}, - new UserEntity{DateOfBirth = DateTime.Parse("01/20/2012",UsCultureInfo.DateTimeFormat)}, - new UserEntity{DateOfBirth = DateTime.Parse("01/20/2012",UsCultureInfo.DateTimeFormat)}, + new() {LastName = "ExistLastName", DateOfBirth = DateTime.Parse("01/20/2012",UsCultureInfo.DateTimeFormat)}, + new() {FirstName = "ExistFirstName"}, + new() {DateOfBirth = DateTime.Parse("01/20/2012",UsCultureInfo.DateTimeFormat)}, + new() {DateOfBirth = DateTime.Parse("01/20/2012",UsCultureInfo.DateTimeFormat)}, + new() {DateOfBirth = DateTime.Parse("01/20/2012",UsCultureInfo.DateTimeFormat)}, }; - var mock = users.BuildMockDbSet(); - var userRepository = new TestDbSetRepository(mock); - var service = new MyService(userRepository); - //act - var ex = Assert.ThrowsAsync(() => service.CreateUserIfNotExist(firstName, lastName, dateOfBirth)); - //assert - Assert.AreEqual(expectedError, ex.Message); - - } - - [TestCase("AnyFirstName", "ExistLastName", "01/20/2012")] - public async Task DbSetCreateUser(string firstName, string lastName, DateTime dateOfBirth) - { - //arrange - var userEntities = new List(); - var mock = userEntities.AsQueryable().BuildMockDbSet(); - mock.AddAsync(Arg.Any()) - .Returns(info => null) - .AndDoes(info => userEntities.Add(info.Arg())); - var userRepository = new TestDbSetRepository(mock); - var service = new MyService(userRepository); - //act - await service.CreateUserIfNotExist(firstName, lastName, dateOfBirth); - // assert - var entity = mock.Single(); - Assert.AreEqual(firstName, entity.FirstName); - Assert.AreEqual(lastName, entity.LastName); - Assert.AreEqual(dateOfBirth, entity.DateOfBirth); - } - - [TestCase("AnyFirstName", "ExistLastName", "01/20/2012")] - public async Task DbSetCreatedFromCollectionCreateUser(string firstName, string lastName, DateTime dateOfBirth) - { - //arrange - var userEntities = new List(); - var mock = userEntities.BuildMockDbSet(); - mock.AddAsync(Arg.Any()) - .Returns(info => null) - .AndDoes(info => userEntities.Add(info.Arg())); - var userRepository = new TestDbSetRepository(mock); - var service = new MyService(userRepository); - //act - await service.CreateUserIfNotExist(firstName, lastName, dateOfBirth); - // assert - var entity = mock.Single(); - Assert.AreEqual(firstName, entity.FirstName); - Assert.AreEqual(lastName, entity.LastName); - Assert.AreEqual(dateOfBirth, entity.DateOfBirth); - } - - [TestCase("01/20/2012", "06/20/2018", 5)] - [TestCase("01/20/2012", "06/20/2012", 4)] - [TestCase("01/20/2012", "02/20/2012", 3)] - [TestCase("01/20/2010", "02/20/2011", 0)] - public async Task DbSetGetUserReports(DateTime from, DateTime to, int expectedCount) - { - //arrange - var users = CreateUserList(); - - var mock = users.AsQueryable().BuildMockDbSet(); - var userRepository = new TestDbSetRepository(mock); - var service = new MyService(userRepository); - //act - var result = await service.GetUserReports(from, to); - //assert - Assert.AreEqual(expectedCount, result.Count); - } - - [TestCase("01/20/2012", "06/20/2018", 5)] - [TestCase("01/20/2012", "06/20/2012", 4)] - [TestCase("01/20/2012", "02/20/2012", 3)] - [TestCase("01/20/2010", "02/20/2011", 0)] - public async Task DbSetCreatedFromCollectionGetUserReports(DateTime from, DateTime to, int expectedCount) - { - //arrange - var users = CreateUserList(); - - var mock = users.BuildMockDbSet(); - var userRepository = new TestDbSetRepository(mock); - var service = new MyService(userRepository); - //act - var result = await service.GetUserReports(from, to); - //assert - Assert.AreEqual(expectedCount, result.Count); - } - - [TestCase] - public async Task DbSetGetAllUserEntity() - { - //arrange - var users = CreateUserList(); - var mock = users.AsQueryable().BuildMockDbSet(); - var userRepository = new TestDbSetRepository(mock); - //act - var result = await userRepository.GetAll(); - //assert - Assert.AreEqual(users.Count, result.Count); - } - - [TestCase] - public async Task DbSetCreatedFromCollectionGetAllUserEntity() - { - //arrange - var users = CreateUserList(); - var mock = users.BuildMockDbSet(); - var userRepository = new TestDbSetRepository(mock); - //act - var result = await userRepository.GetAll(); - //assert - Assert.AreEqual(users.Count, result.Count); - } - - [TestCase] - public async Task DbSetGetAllUserEntitiesAsync() - { - // arrange - var users = CreateUserList(); - - var mockDbSet = users.AsQueryable().BuildMockDbSet(); - var userRepository = new TestDbSetRepository(mockDbSet); - - // act - var result = await userRepository.GetAllAsync().ToListAsync(); - - // assert - Assert.AreEqual(users.Count, result.Count); - } - - - [TestCase] - public async Task DbSetGetAllUserEntitiesAsync_ShouldReturnAllEntities_WhenSourceIsChanged() - { - // arrange - var users = new List(); + var mock = users.AsQueryable().BuildMockDbSet(); + var userRepository = new TestDbSetRepository(mock); + var service = new MyService(userRepository); + //act + var ex = Assert.ThrowsAsync(() => service.CreateUserIfNotExist(firstName, lastName, dateOfBirth)); + //assert + Assert.That(expectedError, Is.EqualTo(ex.Message)); + } - var mockDbSet = users.AsQueryable().BuildMockDbSet(); - var userRepository = new TestDbSetRepository(mockDbSet); + [TestCase("AnyFirstName", "AnyExistLastName", "01/20/2012", "Users with DateOfBirth more than limit")] + [TestCase("ExistFirstName", "AnyExistLastName", "02/20/2012", "User with FirstName already exist")] + [TestCase("AnyFirstName", "ExistLastName", "01/20/2012", "User already exist")] + public void DbSetCreatedFromCollectionCreateUserIfNotExist(string firstName, string lastName, DateTime dateOfBirth, string expectedError) + { + //arrange + var users = new List + { + new() {LastName = "ExistLastName", DateOfBirth = DateTime.Parse("01/20/2012",UsCultureInfo.DateTimeFormat)}, + new() {FirstName = "ExistFirstName"}, + new() {DateOfBirth = DateTime.Parse("01/20/2012",UsCultureInfo.DateTimeFormat)}, + new() {DateOfBirth = DateTime.Parse("01/20/2012",UsCultureInfo.DateTimeFormat)}, + new() {DateOfBirth = DateTime.Parse("01/20/2012",UsCultureInfo.DateTimeFormat)}, + }; + var mock = users.BuildMockDbSet(); + var userRepository = new TestDbSetRepository(mock); + var service = new MyService(userRepository); + //act + var ex = Assert.ThrowsAsync(() => service.CreateUserIfNotExist(firstName, lastName, dateOfBirth)); + //assert + Assert.That(expectedError, Is.EqualTo(ex.Message)); + } - // act - var result1 = await userRepository.GetAllAsync().ToListAsync(); - users.AddRange(CreateUserList()); - var result2 = await userRepository.GetAllAsync().ToListAsync(); + [TestCase("AnyFirstName", "ExistLastName", "01/20/2012")] + public async Task DbSetCreateUser(string firstName, string lastName, DateTime dateOfBirth) + { + //arrange + var userEntities = new List(); + var mock = userEntities.AsQueryable().BuildMockDbSet(); + mock.AddAsync(Arg.Any()) + .Returns(info => null) + .AndDoes(info => userEntities.Add(info.Arg())); + var userRepository = new TestDbSetRepository(mock); + var service = new MyService(userRepository); + //act + await service.CreateUserIfNotExist(firstName, lastName, dateOfBirth); + // assert + var entity = mock.Single(); + Assert.That(firstName, Is.EqualTo(entity.FirstName)); + Assert.That(lastName, Is.EqualTo(entity.LastName)); + Assert.That(dateOfBirth, Is.EqualTo(entity.DateOfBirth)); + } - // assert - Assert.AreEqual(0, result1.Count); - Assert.AreEqual(users.Count, result2.Count); - } + [TestCase("AnyFirstName", "ExistLastName", "01/20/2012")] + public async Task DbSetCreatedFromCollectionCreateUser(string firstName, string lastName, DateTime dateOfBirth) + { + //arrange + var userEntities = new List(); + var mock = userEntities.BuildMockDbSet(); + mock.AddAsync(Arg.Any()) + .Returns(info => null) + .AndDoes(info => userEntities.Add(info.Arg())); + var userRepository = new TestDbSetRepository(mock); + var service = new MyService(userRepository); + //act + await service.CreateUserIfNotExist(firstName, lastName, dateOfBirth); + // assert + var entity = mock.Single(); + Assert.That(firstName, Is.EqualTo(entity.FirstName)); + Assert.That(lastName, Is.EqualTo(entity.LastName)); + Assert.That(dateOfBirth, Is.EqualTo(entity.DateOfBirth)); + } - [TestCase] - public async Task DbSetCreatedFromCollectionGetAllUserEntitiesAsync() - { - // arrange - var users = CreateUserList(); + [TestCase("01/20/2012", "06/20/2018", 5)] + [TestCase("01/20/2012", "06/20/2012", 4)] + [TestCase("01/20/2012", "02/20/2012", 3)] + [TestCase("01/20/2010", "02/20/2011", 0)] + public async Task DbSetGetUserReports(DateTime from, DateTime to, int expectedCount) + { + //arrange + var users = CreateUserList(); + + var mock = users.AsQueryable().BuildMockDbSet(); + var userRepository = new TestDbSetRepository(mock); + var service = new MyService(userRepository); + //act + var result = await service.GetUserReports(from, to); + //assert + Assert.That(expectedCount, Is.EqualTo(result.Count)); + } + + [TestCase("01/20/2012", "06/20/2018", 5)] + [TestCase("01/20/2012", "06/20/2012", 4)] + [TestCase("01/20/2012", "02/20/2012", 3)] + [TestCase("01/20/2010", "02/20/2011", 0)] + public async Task DbSetCreatedFromCollectionGetUserReports(DateTime from, DateTime to, int expectedCount) + { + //arrange + var users = CreateUserList(); + + var mock = users.BuildMockDbSet(); + var userRepository = new TestDbSetRepository(mock); + var service = new MyService(userRepository); + //act + var result = await service.GetUserReports(from, to); + //assert + Assert.That(expectedCount, Is.EqualTo(result.Count)); + } - var mockDbSet = users.BuildMockDbSet(); - var userRepository = new TestDbSetRepository(mockDbSet); + [TestCase] + public async Task DbSetGetAllUserEntity() + { + //arrange + var users = CreateUserList(); + var mock = users.AsQueryable().BuildMockDbSet(); + var userRepository = new TestDbSetRepository(mock); + //act + var result = await userRepository.GetAll(); + //assert + Assert.That(users.Count, Is.EqualTo(result.Count)); + } + + [TestCase] + public async Task DbSetCreatedFromCollectionGetAllUserEntity() + { + //arrange + var users = CreateUserList(); + var mock = users.BuildMockDbSet(); + var userRepository = new TestDbSetRepository(mock); + //act + var result = await userRepository.GetAll(); + //assert + Assert.That(users.Count, Is.EqualTo(result.Count)); + } - // act - var result = await userRepository.GetAllAsync().ToListAsync(); + [TestCase] + public async Task DbSetGetAllUserEntitiesAsync() + { + // arrange + var users = CreateUserList(); - // assert - Assert.AreEqual(users.Count, result.Count); - } + var mockDbSet = users.AsQueryable().BuildMockDbSet(); + var userRepository = new TestDbSetRepository(mockDbSet); - [TestCase] - public async Task DbSetGetOneUserTntityAsync() - { - // arrange - var users = CreateUserList(); + // act + var result = await userRepository.GetAllAsync().ToListAsync(); - var mockDbSet = users.AsQueryable().BuildMockDbSet(); - var userRepository = new TestDbSetRepository(mockDbSet); + // assert + Assert.That(users.Count, Is.EqualTo(result.Count)); + } - // act - var result = await userRepository.GetAllAsync() - .Where(user => user.FirstName == "FirstName1") - .FirstOrDefaultAsync(); + [TestCase] + public async Task DbSetGetAllUserEntitiesAsync_ShouldReturnAllEntities_WhenSourceIsChanged() + { + // arrange + var users = new List(); - // assert - Assert.AreEqual(users.First(), result); - } + var mockDbSet = users.AsQueryable().BuildMockDbSet(); + var userRepository = new TestDbSetRepository(mockDbSet); - [TestCase] - public async Task DbSetCreatedFromCollectionGetOneUserTntityAsync() - { - // arrange - var users = CreateUserList(); + // act + var result1 = await userRepository.GetAllAsync().ToListAsync(); + users.AddRange(CreateUserList()); + var result2 = await userRepository.GetAllAsync().ToListAsync(); + + // assert + Assert.That(0, Is.EqualTo(result1.Count)); + Assert.That(users.Count, Is.EqualTo(result2.Count)); + } + + [TestCase] + public async Task DbSetCreatedFromCollectionGetAllUserEntitiesAsync() + { + // arrange + var users = CreateUserList(); + + var mockDbSet = users.BuildMockDbSet(); + var userRepository = new TestDbSetRepository(mockDbSet); + + // act + var result = await userRepository.GetAllAsync().ToListAsync(); + + // assert + Assert.That(users.Count, Is.EqualTo(result.Count)); + } + + [TestCase] + public async Task DbSetGetOneUserTntityAsync() + { + // arrange + var users = CreateUserList(); + + var mockDbSet = users.AsQueryable().BuildMockDbSet(); + var userRepository = new TestDbSetRepository(mockDbSet); + + // act + var result = await userRepository.GetAllAsync() + .Where(user => user.FirstName == "FirstName1") + .FirstOrDefaultAsync(); + + // assert + Assert.That(users.First(), Is.EqualTo(result)); + } - var mockDbSet = users.BuildMockDbSet(); - var userRepository = new TestDbSetRepository(mockDbSet); + [TestCase] + public async Task DbSetCreatedFromCollectionGetOneUserTntityAsync() + { + // arrange + var users = CreateUserList(); + + var mockDbSet = users.BuildMockDbSet(); + var userRepository = new TestDbSetRepository(mockDbSet); - // act - var result = await userRepository.GetAllAsync() - .Where(user => user.FirstName == "FirstName1") - .FirstOrDefaultAsync(); + // act + var result = await userRepository.GetAllAsync() + .Where(user => user.FirstName == "FirstName1") + .FirstOrDefaultAsync(); - // assert - Assert.AreEqual(users.First(), result); - } + // assert + Assert.That(users.First(), Is.EqualTo(result)); + } - private static List CreateUserList() => new List + [TestCase] + public void GetUsersByFirstName_ExpressionVisitorMissing_ThrowsException() + { + // arrange + var users = CreateUserList(); + + var mockDbSet = users.AsQueryable().BuildMockDbSet(); + var userRepository = new TestDbSetRepository(mockDbSet); + + // act + var exception = Assert.ThrowsAsync(() => userRepository.GetUsersByFirstName("naME")); + + // assert + Assert.That( + exception.Message, + Is.EqualTo( + "The 'ILike' method is not supported because the query has switched to client-evaluation. " + + "This usually happens when the arguments to the method cannot be translated to server. " + + "Rewrite the query to avoid client evaluation of arguments so that method can be translated to server.")); + } + + [TestCase] + public async Task GetUsersByFirstName_PartOfNameCaseInsensitiveSearch_AllMatchesReturned() + { + // arrange + var users = CreateUserList(); + + var mockDbSet = users.AsQueryable().BuildMockDbSet(); + var userRepository = new TestDbSetRepository(mockDbSet); + + // act + var result = await userRepository.GetUsersByFirstName("naME"); + + // assert + Assert.That(users.Count, Is.EqualTo(result.Count())); + } + + private static List CreateUserList() => new() { new UserEntity { FirstName = "FirstName1", LastName = "LastName", DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat) }, new UserEntity { FirstName = "FirstName2", LastName = "LastName", DateOfBirth = DateTime.Parse("01/20/2012", UsCultureInfo.DateTimeFormat) }, @@ -346,6 +375,5 @@ public async Task DbSetCreatedFromCollectionGetOneUserTntityAsync() new UserEntity { FirstName = "FirstName3", LastName = "LastName", DateOfBirth = DateTime.Parse("03/20/2012", UsCultureInfo.DateTimeFormat) }, new UserEntity { FirstName = "FirstName5", LastName = "LastName", DateOfBirth = DateTime.Parse("01/20/2018", UsCultureInfo.DateTimeFormat) }, }; - - } + } } diff --git a/src/MockQueryable/MockQueryable.Sample/SampleILikeExpressionVisitor .cs b/src/MockQueryable/MockQueryable.Sample/SampleILikeExpressionVisitor .cs new file mode 100644 index 0000000..53c2bf7 --- /dev/null +++ b/src/MockQueryable/MockQueryable.Sample/SampleILikeExpressionVisitor .cs @@ -0,0 +1,40 @@ +using Microsoft.EntityFrameworkCore; +using System; +using System.Linq.Expressions; + +namespace MockQueryable.Sample +{ + public class SampleILikeExpressionVisitor : ExpressionVisitor + { + private static readonly char[] value = ['%']; + + /// + /// Rewrites the ILike method call to a string.Contains call with a trimmed + /// and lowercased pattern. + /// This is used to simulate the behavior of ILike in PostgreSQL, which is + /// case-insensitive and allows for wildcard matching with '%'. + /// + protected override Expression VisitMethodCall(MethodCallExpression node) + { + if (node.Method.Name != nameof(NpgsqlDbFunctionsExtensions.ILike) || + node.Arguments.Count != 3) + { + return base.VisitMethodCall(node); + } + + var stringExpression = node.Arguments[1]; + var patternExpression = node.Arguments[2]; + + var toLowerPattern = Expression.Call(patternExpression, nameof(string.ToLower), Type.EmptyTypes); + var trimMethod = typeof(string).GetMethod(nameof(string.Trim), [typeof(char[])]); + var trimmedPattern = Expression.Call(toLowerPattern, trimMethod!, Expression.Constant(value)); + + return Expression.Call( + Expression.Call(stringExpression, nameof(string.ToLower), Type.EmptyTypes), + nameof(string.Contains), + Type.EmptyTypes, + trimmedPattern + ); + } + } +} diff --git a/src/MockQueryable/MockQueryable.Sample/TestDbSetRepository.cs b/src/MockQueryable/MockQueryable.Sample/TestDbSetRepository.cs index 59266d0..db72a66 100644 --- a/src/MockQueryable/MockQueryable.Sample/TestDbSetRepository.cs +++ b/src/MockQueryable/MockQueryable.Sample/TestDbSetRepository.cs @@ -5,31 +5,40 @@ namespace MockQueryable.Sample { - public class TestDbSetRepository : IUserRepository + public class TestDbSetRepository : IUserRepository + { + private readonly DbSet _dbSet; + + public TestDbSetRepository(DbSet dbSet) + { + _dbSet = dbSet; + } + + public IQueryable GetQueryable() { - private readonly DbSet _dbSet; + return _dbSet; + } - public TestDbSetRepository(DbSet dbSet) - { - _dbSet = dbSet; - } - public IQueryable GetQueryable() - { - return _dbSet; - } + public async Task CreateUser(UserEntity user) + { + await _dbSet.AddAsync(user); + } - public async Task CreateUser(UserEntity user) - { - await _dbSet.AddAsync(user); - } + public async Task> GetAll() + { + return await _dbSet.ToListAsync(); + } - public async Task> GetAll() { - return await _dbSet.ToListAsync(); - } + public IAsyncEnumerable GetAllAsync() + { + return _dbSet.AsAsyncEnumerable(); + } - public IAsyncEnumerable GetAllAsync() - { - return _dbSet.AsAsyncEnumerable(); - } + public async Task> GetUsersByFirstName(string firstName) + { + return await _dbSet + .Where(x => EF.Functions.ILike(x.FirstName, $"%{firstName}%")) + .ToListAsync(); } + } } \ No newline at end of file