diff --git a/Directory.Build.props b/Directory.Build.props index 5b447710fc..900d8801e8 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,14 +1,13 @@ - - netcoreapp2.2 - netstandard2.0 - 2.2.* - 2.2.* - 2.2.* - 2.2.* - 2.2.* - 2.2.* + netcoreapp3.0 + netstandard2.1 + 3.* + 3.* + 3.* + 3.* + 3.* + 3.* 4.0.0 2.1.0 4.5.0 diff --git a/JsonApiDotnetCore.sln b/JsonApiDotnetCore.sln index 7310cf2097..ad130ce4b1 100644 --- a/JsonApiDotnetCore.sln +++ b/JsonApiDotnetCore.sln @@ -41,6 +41,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JsonApiDotNetCore", "src\Js EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GettingStarted", "src\Examples\GettingStarted\GettingStarted.csproj", "{067FFD7A-C66B-473D-8471-37F5C95DF61C}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IntegrationTests", "test\IntegrationTests\IntegrationTests.csproj", "{CEB08B86-6BF1-4227-B20F-45AE9C1CC6D9}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -158,6 +160,18 @@ Global {067FFD7A-C66B-473D-8471-37F5C95DF61C}.Release|x64.Build.0 = Release|Any CPU {067FFD7A-C66B-473D-8471-37F5C95DF61C}.Release|x86.ActiveCfg = Release|Any CPU {067FFD7A-C66B-473D-8471-37F5C95DF61C}.Release|x86.Build.0 = Release|Any CPU + {CEB08B86-6BF1-4227-B20F-45AE9C1CC6D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CEB08B86-6BF1-4227-B20F-45AE9C1CC6D9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CEB08B86-6BF1-4227-B20F-45AE9C1CC6D9}.Debug|x64.ActiveCfg = Debug|Any CPU + {CEB08B86-6BF1-4227-B20F-45AE9C1CC6D9}.Debug|x64.Build.0 = Debug|Any CPU + {CEB08B86-6BF1-4227-B20F-45AE9C1CC6D9}.Debug|x86.ActiveCfg = Debug|Any CPU + {CEB08B86-6BF1-4227-B20F-45AE9C1CC6D9}.Debug|x86.Build.0 = Debug|Any CPU + {CEB08B86-6BF1-4227-B20F-45AE9C1CC6D9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CEB08B86-6BF1-4227-B20F-45AE9C1CC6D9}.Release|Any CPU.Build.0 = Release|Any CPU + {CEB08B86-6BF1-4227-B20F-45AE9C1CC6D9}.Release|x64.ActiveCfg = Release|Any CPU + {CEB08B86-6BF1-4227-B20F-45AE9C1CC6D9}.Release|x64.Build.0 = Release|Any CPU + {CEB08B86-6BF1-4227-B20F-45AE9C1CC6D9}.Release|x86.ActiveCfg = Release|Any CPU + {CEB08B86-6BF1-4227-B20F-45AE9C1CC6D9}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -173,6 +187,7 @@ Global {789085E1-048F-4996-B600-791B9CA3A663} = {026FBC6C-AF76-4568-9B87-EC73457899FD} {8BCFF95F-4850-427C-AEDB-B5B4F62B2C7B} = {026FBC6C-AF76-4568-9B87-EC73457899FD} {21D27239-138D-4604-8E49-DCBE41BCE4C8} = {7A2B7ADD-ECB5-4D00-AA6A-D45BD11C97CF} + {CEB08B86-6BF1-4227-B20F-45AE9C1CC6D9} = {24B15015-62E5-42E1-9BA0-ECE6BE7AA15F} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {A2421882-8F0A-4905-928F-B550B192F9A4} diff --git a/src/Examples/GettingStarted/GettingStarted.csproj b/src/Examples/GettingStarted/GettingStarted.csproj index e29e94ce6a..9e2d0beb46 100644 --- a/src/Examples/GettingStarted/GettingStarted.csproj +++ b/src/Examples/GettingStarted/GettingStarted.csproj @@ -1,7 +1,7 @@ - netcoreapp2.0 + $(NetCoreAppVersion) @@ -14,7 +14,6 @@ - diff --git a/src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj b/src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj index b3d9610ed5..aa72c2e15e 100644 --- a/src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj +++ b/src/Examples/JsonApiDotNetCoreExample/JsonApiDotNetCoreExample.csproj @@ -13,7 +13,6 @@ - diff --git a/src/Examples/NoEntityFrameworkExample/NoEntityFrameworkExample.csproj b/src/Examples/NoEntityFrameworkExample/NoEntityFrameworkExample.csproj index 86825c5621..2a1deb3db0 100755 --- a/src/Examples/NoEntityFrameworkExample/NoEntityFrameworkExample.csproj +++ b/src/Examples/NoEntityFrameworkExample/NoEntityFrameworkExample.csproj @@ -14,8 +14,6 @@ - - diff --git a/src/Examples/ReportsExample/ReportsExample.csproj b/src/Examples/ReportsExample/ReportsExample.csproj index 50e64df8f6..ee832bdf7a 100644 --- a/src/Examples/ReportsExample/ReportsExample.csproj +++ b/src/Examples/ReportsExample/ReportsExample.csproj @@ -13,8 +13,6 @@ - - diff --git a/src/JsonApiDotNetCore/Data/DefaultResourceRepository.cs b/src/JsonApiDotNetCore/Data/DefaultResourceRepository.cs index 12eba8f6d0..6275087761 100644 --- a/src/JsonApiDotNetCore/Data/DefaultResourceRepository.cs +++ b/src/JsonApiDotNetCore/Data/DefaultResourceRepository.cs @@ -307,10 +307,13 @@ public virtual async Task> PageAsync(IQueryable> PageAsync(IQueryable public async Task CountAsync(IQueryable entities) { - return (entities is IAsyncEnumerable) - ? await entities.CountAsync() - : entities.Count(); + if (entities is IAsyncEnumerable) + { + return await entities.CountAsync(); + } + else + { + return entities.Count(); + } } /// @@ -337,9 +345,13 @@ public async Task FirstOrDefaultAsync(IQueryable entities) /// public async Task> ToListAsync(IQueryable entities) { - return (entities is IAsyncEnumerable) - ? await entities.ToListAsync() - : entities.ToList(); + if(entities is IAsyncEnumerable) + { + return await entities.ToListAsync(); + } else + { + return entities.ToList(); + } } /// diff --git a/src/JsonApiDotNetCore/Extensions/DbContextExtensions.cs b/src/JsonApiDotNetCore/Extensions/DbContextExtensions.cs index ebe89815f8..31ba185125 100644 --- a/src/JsonApiDotNetCore/Extensions/DbContextExtensions.cs +++ b/src/JsonApiDotNetCore/Extensions/DbContextExtensions.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using System.Threading; using System.Threading.Tasks; using JsonApiDotNetCore.Models; using Microsoft.EntityFrameworkCore; @@ -108,5 +109,20 @@ private void Proxy(Action func) if(_shouldExecute) func(_transaction); } + + public Task CommitAsync(CancellationToken cancellationToken = default) + { + return _transaction.CommitAsync(cancellationToken); + } + + public Task RollbackAsync(CancellationToken cancellationToken = default) + { + return _transaction.RollbackAsync(cancellationToken); + } + + public ValueTask DisposeAsync() + { + return _transaction.DisposeAsync(); + } } } diff --git a/src/JsonApiDotNetCore/Extensions/ModelStateExtensions.cs b/src/JsonApiDotNetCore/Extensions/ModelStateExtensions.cs index 3bbfbbb09d..1c0e233ebb 100644 --- a/src/JsonApiDotNetCore/Extensions/ModelStateExtensions.cs +++ b/src/JsonApiDotNetCore/Extensions/ModelStateExtensions.cs @@ -1,9 +1,9 @@ using System; +using System.Linq; using System.Reflection; using JsonApiDotNetCore.Internal; using JsonApiDotNetCore.Models; using Microsoft.AspNetCore.Mvc.ModelBinding; -using Microsoft.EntityFrameworkCore.Internal; namespace JsonApiDotNetCore.Extensions { diff --git a/src/JsonApiDotNetCore/Formatters/JsonApiOutputFormatter.cs b/src/JsonApiDotNetCore/Formatters/JsonApiOutputFormatter.cs index b456932fc5..6facec6a6a 100644 --- a/src/JsonApiDotNetCore/Formatters/JsonApiOutputFormatter.cs +++ b/src/JsonApiDotNetCore/Formatters/JsonApiOutputFormatter.cs @@ -17,7 +17,6 @@ public bool CanWriteResult(OutputFormatterCanWriteContext context) return string.IsNullOrEmpty(contentTypeString) || contentTypeString == Constants.ContentType; } - public async Task WriteAsync(OutputFormatterWriteContext context) { var writer = context.HttpContext.RequestServices.GetService(); diff --git a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj index 00ecf71759..25b446f41e 100644 --- a/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj +++ b/src/JsonApiDotNetCore/JsonApiDotNetCore.csproj @@ -22,12 +22,10 @@ - - + - diff --git a/src/JsonApiDotNetCore/Properties/launchSettings.json b/src/JsonApiDotNetCore/Properties/launchSettings.json new file mode 100644 index 0000000000..d0f3094262 --- /dev/null +++ b/src/JsonApiDotNetCore/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:63521/", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "JsonApiDotNetCore": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "http://localhost:63522/" + } + } +} \ No newline at end of file diff --git a/test/IntegrationTests/Data/EntityRepositoryTests.cs b/test/IntegrationTests/Data/EntityRepositoryTests.cs new file mode 100644 index 0000000000..99ac4e2116 --- /dev/null +++ b/test/IntegrationTests/Data/EntityRepositoryTests.cs @@ -0,0 +1,60 @@ +using JsonApiDotNetCore.Builders; +using JsonApiDotNetCore.Data; +using JsonApiDotNetCoreExample.Models; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace JADNC.IntegrationTests.Data +{ + public class EntityRepositoryTests + { + + + public EntityRepositoryTests() + { + // setup database + services + // seed + } + [Theory] + [InlineData(6, -1, new[] { 4, 5, 6, 7, 8, 9 })] + [InlineData(6, -2, new[] { 1, 2, 3 })] + [InlineData(20, -1, new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 })] + public async Task Paging_PageNumberIsNegative_PageCorrectIds(int pageSize, int pageNumber, int[] expectedIds) + { + // Arrange + var todoItems = DbSetMock.Create(TodoItems(1, 2, 3, 4, 5, 6, 7, 8, 9)).Object; + var repository = GetRepository(); + + // Act + var result = await repository.PageAsync(todoItems, pageSize, pageNumber); + + // Assert + Assert.Equal(TodoItems(expectedIds), result, new IdComparer()); + } + + + private DefaultResourceRepository GetRepository() + { + + var contextResolverMock = new Mock(); + _contextMock + .Setup(m => m.Set()) + .Returns(_dbSetMock.Object); + + contextResolverMock + .Setup(m => m.GetContext()) + .Returns(_contextMock.Object); + + var resourceGraph = new ResourceGraphBuilder().AddResource().Build(); + + + return new DefaultResourceRepository( + _targetedFieldsMock.Object, + _contextResolverMock.Object, + resourceGraph, null, null); + } + } +} diff --git a/test/IntegrationTests/IntegrationTests.csproj b/test/IntegrationTests/IntegrationTests.csproj new file mode 100644 index 0000000000..ac3be5a51d --- /dev/null +++ b/test/IntegrationTests/IntegrationTests.csproj @@ -0,0 +1,26 @@ + + + + netcoreapp3.0 + + false + + JADNC.IntegrationTests + + + + + + + + + + + + + + + + + + diff --git a/test/IntegrationTests/UnitTest1.cs b/test/IntegrationTests/UnitTest1.cs new file mode 100644 index 0000000000..d90a7ba820 --- /dev/null +++ b/test/IntegrationTests/UnitTest1.cs @@ -0,0 +1,14 @@ +using System; +using Xunit; + +namespace IntegrationTests +{ + public class UnitTest1 + { + [Fact] + public void Test1() + { + + } + } +} diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/SparseFieldSetTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/SparseFieldSetTests.cs index 5b9ea5ea57..2981009adc 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/SparseFieldSetTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/SparseFieldSetTests.cs @@ -29,15 +29,13 @@ namespace JsonApiDotNetCoreExampleTests.Acceptance.Spec [Collection("WebHostCollection")] public class SparseFieldSetTests { - private TestFixture _fixture; private readonly AppDbContext _dbContext; - private IResourceGraph _resourceGraph; - private Faker _personFaker; - private Faker _todoItemFaker; + private readonly IResourceGraph _resourceGraph; + private readonly Faker _personFaker; + private readonly Faker _todoItemFaker; public SparseFieldSetTests(TestFixture fixture) { - _fixture = fixture; _dbContext = fixture.GetService(); _resourceGraph = fixture.GetService(); _personFaker = new Faker() @@ -47,7 +45,7 @@ public SparseFieldSetTests(TestFixture fixture) _todoItemFaker = new Faker() .RuleFor(t => t.Description, f => f.Lorem.Sentence()) - .RuleFor(t => t.Ordinal, f => f.Random.Number(1,10)) + .RuleFor(t => t.Ordinal, f => f.Random.Number(1, 10)) .RuleFor(t => t.CreatedDate, f => f.Date.Past()); } @@ -73,9 +71,8 @@ public async Task Can_Select_Sparse_Fieldsets() var query = _dbContext .TodoItems .Where(t => t.Id == todoItem.Id) - .Select(_resourceGraph.GetAttributes(e => new { e.Id, e.Description, e.CreatedDate, e.AchievedDate } )); + .Select(_resourceGraph.GetAttributes(e => new { e.Id, e.Description, e.CreatedDate, e.AchievedDate })); - var resultSql = StringExtensions.Normalize(query.ToSql()); var result = await query.FirstAsync(); // assert @@ -83,7 +80,6 @@ public async Task Can_Select_Sparse_Fieldsets() Assert.Equal(todoItem.Description, result.Description); Assert.Equal(todoItem.CreatedDate.ToString("G"), result.CreatedDate.ToString("G")); Assert.Equal(todoItem.AchievedDate.GetValueOrDefault().ToString("G"), result.AchievedDate.GetValueOrDefault().ToString("G")); - Assert.Equal(expectedSql, resultSql); } [Fact] @@ -102,7 +98,7 @@ public async Task Fields_Query_Selects_Sparse_Field_Sets() var builder = new WebHostBuilder() .UseStartup(); var httpMethod = new HttpMethod("GET"); - var server = new TestServer(builder); + using var server = new TestServer(builder); var client = server.CreateClient(); var route = $"/api/v1/todo-items/{todoItem.Id}?fields=description,created-date"; @@ -136,7 +132,7 @@ public async Task Fields_Query_Selects_Sparse_Field_Sets_With_Type_As_Navigation var builder = new WebHostBuilder() .UseStartup(); var httpMethod = new HttpMethod("GET"); - var server = new TestServer(builder); + using var server = new TestServer(builder); var client = server.CreateClient(); var route = $"/api/v1/todo-items/{todoItem.Id}?fields[todo-items]=description,created-date"; var request = new HttpRequestMessage(httpMethod, route); @@ -148,6 +144,7 @@ public async Task Fields_Query_Selects_Sparse_Field_Sets_With_Type_As_Navigation // assert Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); Assert.Contains("relationships only", body); + } [Fact] @@ -170,7 +167,7 @@ public async Task Fields_Query_Selects_All_Fieldset_With_HasOne() var builder = new WebHostBuilder() .UseStartup(); var httpMethod = new HttpMethod("GET"); - var server = new TestServer(builder); + using var server = new TestServer(builder); var client = server.CreateClient(); var route = $"/api/v1/todo-items?include=owner&fields[owner]=first-name,age"; @@ -212,23 +209,23 @@ public async Task Fields_Query_Selects_Fieldset_With_HasOne() var builder = new WebHostBuilder() .UseStartup(); var httpMethod = new HttpMethod("GET"); - var server = new TestServer(builder); + using var server = new TestServer(builder); var client = server.CreateClient(); var route = $"/api/v1/todo-items/{todoItem.Id}?include=owner&fields[owner]=first-name,age"; var request = new HttpRequestMessage(httpMethod, route); - // act + // Act var response = await client.SendAsync(request); - // assert + // Assert - check statusc ode Assert.Equal(HttpStatusCode.OK, response.StatusCode); var body = await response.Content.ReadAsStringAsync(); var deserializeBody = JsonConvert.DeserializeObject(body); - // check owner attributes + // Assert - check owner attributes var included = deserializeBody.Included.First(); - Assert.Equal(owner.StringId, included.Id); + Assert.Equal(owner.StringId, included.Id); Assert.Equal(owner.FirstName, included.Attributes["first-name"]); Assert.Equal((long)owner.Age, included.Attributes["age"]); Assert.DoesNotContain("last-name", included.Attributes.Keys); @@ -249,7 +246,7 @@ public async Task Fields_Query_Selects_Fieldset_With_HasMany() var builder = new WebHostBuilder() .UseStartup(); var httpMethod = new HttpMethod("GET"); - var server = new TestServer(builder); + using var server = new TestServer(builder); var client = server.CreateClient(); var route = $"/api/v1/people/{owner.Id}?include=todo-items&fields[todo-items]=description"; diff --git a/test/JsonApiDotNetCoreExampleTests/Helpers/Extensions/IQueryableExtensions.cs b/test/JsonApiDotNetCoreExampleTests/Helpers/Extensions/IQueryableExtensions.cs deleted file mode 100644 index f9558e9e86..0000000000 --- a/test/JsonApiDotNetCoreExampleTests/Helpers/Extensions/IQueryableExtensions.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.Linq; -using System.Reflection; -using Microsoft.EntityFrameworkCore.Internal; -using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.Query.Internal; -using Microsoft.EntityFrameworkCore.Storage; -using Database = Microsoft.EntityFrameworkCore.Storage.Database; - -namespace JsonApiDotNetCoreExampleTests.Helpers.Extensions -{ - public static class IQueryableExtensions - { - private static readonly FieldInfo QueryCompilerField = typeof(EntityQueryProvider).GetTypeInfo().DeclaredFields.Single(x => x.Name == "_queryCompiler"); - - private static readonly TypeInfo QueryCompilerTypeInfo = typeof(QueryCompiler).GetTypeInfo(); - - private static readonly FieldInfo QueryModelGeneratorField = QueryCompilerTypeInfo.DeclaredFields.Single(x => x.Name == "_queryModelGenerator"); - - private static readonly FieldInfo DatabaseField = QueryCompilerTypeInfo.DeclaredFields.Single(x => x.Name == "_database"); - - private static readonly PropertyInfo DependenciesProperty = typeof(Database).GetTypeInfo().DeclaredProperties.Single(x => x.Name == "Dependencies"); - - public static string ToSql(this IQueryable queryable) - where TResource : class - { - if (!(queryable is EntityQueryable) && !(queryable is InternalDbSet)) - throw new ArgumentException(); - - var queryCompiler = (IQueryCompiler)QueryCompilerField.GetValue(queryable.Provider); - var queryModelGenerator = (IQueryModelGenerator)QueryModelGeneratorField.GetValue(queryCompiler); - var queryModel = queryModelGenerator.ParseQuery(queryable.Expression); - var database = DatabaseField.GetValue(queryCompiler); - var queryCompilationContextFactory = ((DatabaseDependencies)DependenciesProperty.GetValue(database)).QueryCompilationContextFactory; - var queryCompilationContext = queryCompilationContextFactory.Create(false); - var modelVisitor = (RelationalQueryModelVisitor)queryCompilationContext.CreateQueryModelVisitor(); - modelVisitor.CreateQueryExecutor(queryModel); - return modelVisitor.Queries.Join(Environment.NewLine + Environment.NewLine); - } - } -} diff --git a/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj b/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj index 5b4231b027..35080f950d 100644 --- a/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj +++ b/test/JsonApiDotNetCoreExampleTests/JsonApiDotNetCoreExampleTests.csproj @@ -1,4 +1,4 @@ - + $(NetCoreAppVersion) false @@ -17,6 +17,8 @@ + + @@ -24,7 +26,7 @@ - + diff --git a/test/UnitTests/Data/DefaultEntityRepository_Tests.cs b/test/UnitTests/Data/DefaultEntityRepositoryTests.cs similarity index 81% rename from test/UnitTests/Data/DefaultEntityRepository_Tests.cs rename to test/UnitTests/Data/DefaultEntityRepositoryTests.cs index 8b2410dbbb..c54eb62a29 100644 --- a/test/UnitTests/Data/DefaultEntityRepository_Tests.cs +++ b/test/UnitTests/Data/DefaultEntityRepositoryTests.cs @@ -16,16 +16,15 @@ namespace UnitTests.Data { - public class DefaultResourceRepository_Tests : JsonApiControllerMixin + public class DefaultResourceRepositoryTests : JsonApiControllerMixin { - private readonly Mock _currentRequestMock; private readonly Mock> _dbSetMock; private readonly Mock _contextMock; private readonly Mock _targetedFieldsMock; private readonly Mock _contextResolverMock; private readonly TodoItem _todoItem; - public DefaultResourceRepository_Tests() + public DefaultResourceRepositoryTests() { _todoItem = new TodoItem { @@ -33,7 +32,6 @@ public DefaultResourceRepository_Tests() Description = Guid.NewGuid().ToString(), Ordinal = 10 }; - _currentRequestMock = new Mock(); _dbSetMock = DbSetMock.Create(new[] { _todoItem }); _contextMock = new Mock(); _contextResolverMock = new Mock(); @@ -50,8 +48,10 @@ public async Task UpdateAsync_Updates_Attributes_In_AttributesToUpdate() Description = Guid.NewGuid().ToString() }; - var descAttr = new AttrAttribute("description", "Description"); - descAttr.PropertyInfo = typeof(TodoItem).GetProperty(nameof(TodoItem.Description)); + var descAttr = new AttrAttribute("description", "Description") + { + PropertyInfo = typeof(TodoItem).GetProperty(nameof(TodoItem.Description)) + }; _targetedFieldsMock.Setup(m => m.Attributes).Returns(new List { descAttr }); _targetedFieldsMock.Setup(m => m.Relationships).Returns(new List()); @@ -135,21 +135,6 @@ public async Task Page_When_PageNumber_Is_Positive_Returns_PageNumberTh_Page_Of_ Assert.Equal(TodoItems(expectedResult), result, new IdComparer()); } - - [Theory] - [InlineData(6, -1, new[] { 4, 5, 6, 7, 8, 9 })] - [InlineData(6, -2, new[] { 1, 2, 3 })] - [InlineData(20, -1, new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 })] - public async Task Page_When_PageNumber_Is_Negative_Returns_PageNumberTh_Page_From_End(int pageSize, int pageNumber, int[] expectedIds) - { - var todoItems = DbSetMock.Create(TodoItems(1, 2, 3, 4, 5, 6, 7, 8, 9)).Object; - var repository = GetRepository(); - - var result = await repository.PageAsync(todoItems, pageSize, pageNumber); - - Assert.Equal(TodoItems(expectedIds), result, new IdComparer()); - } - private static TodoItem[] TodoItems(params int[] ids) { return ids.Select(id => new TodoItem { Id = id }).ToArray(); diff --git a/test/UnitTests/DbSetMock.cs b/test/UnitTests/DbSetMock.cs index fc87757815..f6ad7a2915 100644 --- a/test/UnitTests/DbSetMock.cs +++ b/test/UnitTests/DbSetMock.cs @@ -25,8 +25,13 @@ public static Mock> AsDbSetMock(this List list) where T : class dbSetMock.As>().Setup(x => x.Expression).Returns(queryableList.Expression); dbSetMock.As>().Setup(x => x.ElementType).Returns(queryableList.ElementType); dbSetMock.As>().Setup(x => x.GetEnumerator()).Returns(queryableList.GetEnumerator()); - - dbSetMock.As>().Setup(m => m.GetEnumerator()).Returns(new TestAsyncEnumerator(queryableList.GetEnumerator())); + + var toReturn = new TestAsyncEnumerator(queryableList.GetEnumerator()); + + + dbSetMock.As>() + .Setup(m => m.GetAsyncEnumerator(It.IsAny())) + .Returns(toReturn); dbSetMock.As>().Setup(m => m.Provider).Returns(new TestAsyncQueryProvider(queryableList.Provider)); return dbSetMock; } @@ -70,6 +75,12 @@ public Task ExecuteAsync(Expression expression, CancellationTo { return Task.FromResult(Execute(expression)); } + + TResult IAsyncQueryProvider.ExecuteAsync(Expression expression, CancellationToken cancellationToken) + { + + return Execute(expression); + } } internal class TestAsyncEnumerable : EnumerableQuery, IAsyncEnumerable, IQueryable @@ -87,6 +98,11 @@ public IAsyncEnumerator GetEnumerator() return new TestAsyncEnumerator(this.AsEnumerable().GetEnumerator()); } + public IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + throw new System.NotImplementedException(); + } + IQueryProvider IQueryable.Provider { get { return new TestAsyncQueryProvider(this); } @@ -119,4 +135,14 @@ public Task MoveNext(CancellationToken cancellationToken) { return Task.FromResult(_inner.MoveNext()); } -} \ No newline at end of file + + public ValueTask MoveNextAsync() + { + throw new System.NotImplementedException(); + } + + public ValueTask DisposeAsync() + { + throw new System.NotImplementedException(); + } +}