├── googlea6bd68d4a55b1e59.html ├── src ├── EntityFrameworkCore.Testing.Common.Tests │ ├── TestEntity.cs │ ├── NotRegisteredEntity.cs │ ├── TestReadOnlyEntity.cs │ ├── TestViewModel.cs │ ├── MappingProfile.cs │ ├── BaseTestEntity.cs │ ├── BaseForTests.cs │ ├── AsyncEnumerableTests.cs │ ├── Issue114Tests.cs │ ├── Issue126Tests.cs │ ├── TestDbContext.cs │ ├── Issue49Tests.cs │ ├── EntityFrameworkCore.Testing.Common.Tests.csproj │ ├── Issue117Tests.cs │ ├── Issue88Tests.cs │ ├── BaseForDbSetTests.cs │ ├── BaseForReadOnlyDbSetTests.cs │ └── ReadOnlyDbSetExceptionTests.cs ├── EntityFrameworkCore.Testing.Moq.Tests │ ├── Issue114Tests.cs │ ├── Issue117Tests.cs │ ├── ByPropertyDbSetTests.cs │ ├── ByTypeReadOnlyDbSetTests.cs │ ├── ByPropertyReadOnlyDbSetTests.cs │ ├── Issue49Tests.cs │ ├── DbContextTestsUsingType.cs │ ├── DbContextTestsUsingConstructorParameters.cs │ ├── Issue126Tests.cs │ ├── Issue88Tests.cs │ ├── ByTypeReadOnlyDbSetExceptionTests.cs │ ├── ByPropertyReadOnlyDbSetExceptionTests.cs │ ├── ByTypeDbSetTests.cs │ ├── EntityFrameworkCore.Testing.Moq.Tests.csproj │ ├── CreateFactoryTests.cs │ ├── BaseForDbContextTests.cs │ ├── BaseForDbSetTests.cs │ ├── Issue1Tests.cs │ ├── Issue4Tests.cs │ ├── Issue6Tests.cs │ └── BaseForDbQueryTests.cs ├── EntityFrameworkCore.Testing.NSubstitute.Tests │ ├── Issue114Tests.cs │ ├── Issue117Tests.cs │ ├── ByPropertyDbSetTests.cs │ ├── ByTypeReadOnlyDbSetTests.cs │ ├── ByPropertyReadOnlyDbSetTests.cs │ ├── Issue49Tests.cs │ ├── DbContextTestsUsingType.cs │ ├── DbContextTestsUsingConstructorParameters.cs │ ├── Issue126Tests.cs │ ├── Issue88Tests.cs │ ├── ByTypeReadOnlyDbSetExceptionTests.cs │ ├── ByPropertyReadOnlyDbSetExceptionTests.cs │ ├── ByTypeDbSetTests.cs │ ├── EntityFrameworkCore.Testing.NSubstitute.Tests.csproj │ ├── CreateFactoryTests.cs │ ├── BaseForDbContextTests.cs │ ├── BaseForDbSetTests.cs │ ├── Issue1Tests.cs │ ├── Issue4Tests.cs │ ├── Issue6Tests.cs │ └── BaseForDbQueryTests.cs ├── EntityFrameworkCore.DefaultBehaviour.Tests │ ├── Issue114Tests.cs │ ├── Issue117Tests.cs │ ├── Issue49Tests.cs │ ├── ByTypeReadOnlyDbSetExceptionTests.cs │ ├── Issue88Tests.cs │ ├── EntityFrameworkCore.DefaultBehaviour.Tests.csproj │ ├── ByTypeReadOnlyDbSetTests.cs │ ├── DbContextTests.cs │ └── ByTypeDbSetTests.cs ├── EntityFrameworkCore.Testing.Common │ ├── QueryRootExpression.cs │ ├── AsyncEnumerator.cs │ ├── Helpers │ │ ├── MockedDbContextFactoryOptions.cs │ │ ├── IMockedDbContextBuilder.cs │ │ ├── BaseMockedDbContextBuilder.cs │ │ ├── BaseMockedDbContextFactory.cs │ │ ├── ExpressionHelper.cs │ │ └── ParameterMatchingHelper.cs │ ├── AsyncEnumerable.cs │ ├── EntityFrameworkCore.Testing.Common.csproj │ ├── ExceptionMessages.Designer.cs │ ├── AsyncQueryProvider.cs │ └── ExceptionMessages.resx ├── EntityFrameworkCore.Testing.Moq │ ├── Helpers │ │ └── MockedDbContextBuilder.cs │ ├── EntityFrameworkCore.Testing.Moq.csproj │ ├── Extensions │ │ ├── QueryProviderExtensions.Internal.cs │ │ ├── ReadOnlyDbSetExtensions.cs │ │ ├── DbSetExtensions.Internal.cs │ │ └── QueryableExtensions.cs │ └── Create.cs └── EntityFrameworkCore.Testing.NSubstitute │ ├── Helpers │ ├── MockedDbContextBuilder.cs │ └── NoSetUpHandler.cs │ ├── EntityFrameworkCore.Testing.NSubstitute.csproj │ ├── Extensions │ ├── QueryProviderExtensions.Internal.cs │ ├── ReadOnlyDbSetExtensions.cs │ ├── DbSetExtensions.Internal.cs │ └── QueryableExtensions.cs │ └── Create.cs ├── TODO.md ├── LICENSE ├── .github └── workflows │ ├── release.yml │ └── continuous-integration-checks.yml ├── EntityFrameworkCore.Testing.Moq.nuspec ├── EntityFrameworkCore.Testing.NSubstitute.nuspec ├── EntityFrameworkCore.Testing.sln └── .gitignore /googlea6bd68d4a55b1e59.html: -------------------------------------------------------------------------------- 1 | google-site-verification: googlea6bd68d4a55b1e59.html -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Common.Tests/TestEntity.cs: -------------------------------------------------------------------------------- 1 | namespace EntityFrameworkCore.Testing.Common.Tests 2 | { 3 | public class TestEntity : BaseTestEntity { } 4 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Common.Tests/NotRegisteredEntity.cs: -------------------------------------------------------------------------------- 1 | namespace EntityFrameworkCore.Testing.Common.Tests 2 | { 3 | public class NotRegisteredEntity : BaseTestEntity { } 4 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Common.Tests/TestReadOnlyEntity.cs: -------------------------------------------------------------------------------- 1 | namespace EntityFrameworkCore.Testing.Common.Tests 2 | { 3 | public class TestReadOnlyEntity : BaseTestEntity { } 4 | } -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | # TODO 2 | 3 | - Add tests for untested functionality 4 | - Remove repeated set up code 5 | - Unify test structures to assist with cross project comparisons 6 | - Add default behaviour tests for SQL Server provider 7 | -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Common.Tests/TestViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace EntityFrameworkCore.Testing.Common.Tests 4 | { 5 | public class TestViewModel 6 | { 7 | public Guid id { get; set; } 8 | 9 | public string fullName { get; set; } 10 | } 11 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Moq.Tests/Issue114Tests.cs: -------------------------------------------------------------------------------- 1 | namespace EntityFrameworkCore.Testing.Moq.Tests 2 | { 3 | public class Issue114Tests : Common.Tests.Issue114Tests 4 | { 5 | protected override TestDbContext MockedDbContextFactory() 6 | { 7 | return Create.MockedDbContextFor(); 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Moq.Tests/Issue117Tests.cs: -------------------------------------------------------------------------------- 1 | namespace EntityFrameworkCore.Testing.Moq.Tests 2 | { 3 | public class Issue117Tests : Common.Tests.Issue117Tests 4 | { 5 | protected override TestDbContext MockedDbContextFactory() 6 | { 7 | return Create.MockedDbContextFor(); 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.NSubstitute.Tests/Issue114Tests.cs: -------------------------------------------------------------------------------- 1 | namespace EntityFrameworkCore.Testing.NSubstitute.Tests 2 | { 3 | public class Issue114Tests : Common.Tests.Issue114Tests 4 | { 5 | protected override TestDbContext MockedDbContextFactory() 6 | { 7 | return Create.MockedDbContextFor(); 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.NSubstitute.Tests/Issue117Tests.cs: -------------------------------------------------------------------------------- 1 | namespace EntityFrameworkCore.Testing.NSubstitute.Tests 2 | { 3 | public class Issue117Tests : Common.Tests.Issue117Tests 4 | { 5 | protected override TestDbContext MockedDbContextFactory() 6 | { 7 | return Create.MockedDbContextFor(); 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Moq.Tests/ByPropertyDbSetTests.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using EntityFrameworkCore.Testing.Common.Tests; 3 | 4 | namespace EntityFrameworkCore.Testing.Moq.Tests 5 | { 6 | public class ByPropertyDbSetTests : BaseForDbSetTests 7 | { 8 | protected override IQueryable Queryable => MockedDbContext.TestEntities; 9 | } 10 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Common.Tests/MappingProfile.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | 3 | namespace EntityFrameworkCore.Testing.Common.Tests 4 | { 5 | public class MappingProfile : Profile 6 | { 7 | public MappingProfile() 8 | { 9 | CreateMap(); 10 | 11 | CreateMap(); 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.NSubstitute.Tests/ByPropertyDbSetTests.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using EntityFrameworkCore.Testing.Common.Tests; 3 | 4 | namespace EntityFrameworkCore.Testing.NSubstitute.Tests 5 | { 6 | public class ByPropertyDbSetTests : BaseForDbSetTests 7 | { 8 | protected override IQueryable Queryable => MockedDbContext.TestEntities; 9 | } 10 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Moq.Tests/ByTypeReadOnlyDbSetTests.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using EntityFrameworkCore.Testing.Common.Tests; 3 | 4 | namespace EntityFrameworkCore.Testing.Moq.Tests 5 | { 6 | public class ByTypeReadOnlyDbSetTests : BaseForDbQueryTests 7 | { 8 | protected override IQueryable Queryable => MockedDbContext.Set(); 9 | } 10 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Moq.Tests/ByPropertyReadOnlyDbSetTests.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using EntityFrameworkCore.Testing.Common.Tests; 3 | 4 | namespace EntityFrameworkCore.Testing.Moq.Tests 5 | { 6 | public class ByPropertyReadOnlyDbSetTests : BaseForDbQueryTests 7 | { 8 | protected override IQueryable Queryable => MockedDbContext.Set(); 9 | } 10 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.NSubstitute.Tests/ByTypeReadOnlyDbSetTests.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using EntityFrameworkCore.Testing.Common.Tests; 3 | 4 | namespace EntityFrameworkCore.Testing.NSubstitute.Tests 5 | { 6 | public class ByTypeReadOnlyDbSetTests : BaseForDbQueryTests 7 | { 8 | protected override IQueryable Queryable => MockedDbContext.Set(); 9 | } 10 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.NSubstitute.Tests/ByPropertyReadOnlyDbSetTests.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using EntityFrameworkCore.Testing.Common.Tests; 3 | 4 | namespace EntityFrameworkCore.Testing.NSubstitute.Tests 5 | { 6 | public class ByPropertyReadOnlyDbSetTests : BaseForDbQueryTests 7 | { 8 | protected override IQueryable Queryable => MockedDbContext.Set(); 9 | } 10 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Moq.Tests/Issue49Tests.cs: -------------------------------------------------------------------------------- 1 | using EntityFrameworkCore.Testing.Common.Tests; 2 | using NUnit.Framework; 3 | 4 | namespace EntityFrameworkCore.Testing.Moq.Tests 5 | { 6 | public class Issue49Tests : Issue49Tests 7 | { 8 | [SetUp] 9 | public override void SetUp() 10 | { 11 | base.SetUp(); 12 | 13 | DbContext = Create.MockedDbContextFor(); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.NSubstitute.Tests/Issue49Tests.cs: -------------------------------------------------------------------------------- 1 | using EntityFrameworkCore.Testing.Common.Tests; 2 | using NUnit.Framework; 3 | 4 | namespace EntityFrameworkCore.Testing.NSubstitute.Tests 5 | { 6 | public class Issue49Tests : Issue49Tests 7 | { 8 | [SetUp] 9 | public override void SetUp() 10 | { 11 | base.SetUp(); 12 | 13 | DbContext = Create.MockedDbContextFor(); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Moq.Tests/DbContextTestsUsingType.cs: -------------------------------------------------------------------------------- 1 | using EntityFrameworkCore.Testing.Common.Tests; 2 | using NUnit.Framework; 3 | 4 | namespace EntityFrameworkCore.Testing.Moq.Tests 5 | { 6 | public class DbContextTestsUsingType : BaseForDbContextTests 7 | { 8 | [SetUp] 9 | public override void SetUp() 10 | { 11 | base.SetUp(); 12 | 13 | MockedDbContext = Create.MockedDbContextFor(); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.DefaultBehaviour.Tests/Issue114Tests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore; 3 | 4 | namespace EntityFrameworkCore.DefaultBehaviour.Tests 5 | { 6 | public class Issue114Tests : Testing.Common.Tests.Issue114Tests 7 | { 8 | protected override TestDbContext MockedDbContextFactory() 9 | { 10 | return new TestDbContext(new DbContextOptionsBuilder().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options); 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.DefaultBehaviour.Tests/Issue117Tests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore; 3 | 4 | namespace EntityFrameworkCore.DefaultBehaviour.Tests 5 | { 6 | public class Issue117Tests : Testing.Common.Tests.Issue117Tests 7 | { 8 | protected override TestDbContext MockedDbContextFactory() 9 | { 10 | return new TestDbContext(new DbContextOptionsBuilder().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options); 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.NSubstitute.Tests/DbContextTestsUsingType.cs: -------------------------------------------------------------------------------- 1 | using EntityFrameworkCore.Testing.Common.Tests; 2 | using NUnit.Framework; 3 | 4 | namespace EntityFrameworkCore.Testing.NSubstitute.Tests 5 | { 6 | public class DbContextTestsUsingType : BaseForDbContextTests 7 | { 8 | [SetUp] 9 | public override void SetUp() 10 | { 11 | base.SetUp(); 12 | 13 | MockedDbContext = Create.MockedDbContextFor(); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Common.Tests/BaseTestEntity.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace EntityFrameworkCore.Testing.Common.Tests 4 | { 5 | public abstract class BaseTestEntity 6 | { 7 | public Guid Id { get; set; } 8 | 9 | public string FullName { get; set; } 10 | 11 | public decimal Weight { get; set; } 12 | 13 | public decimal Height { get; set; } 14 | 15 | public DateTime DateOfBirth { get; set; } 16 | 17 | public DateTime CreatedAt { get; set; } 18 | 19 | public DateTime LastModifiedAt { get; set; } 20 | } 21 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.DefaultBehaviour.Tests/Issue49Tests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using EntityFrameworkCore.Testing.Common.Tests; 3 | using Microsoft.EntityFrameworkCore; 4 | using NUnit.Framework; 5 | 6 | namespace EntityFrameworkCore.DefaultBehaviour.Tests 7 | { 8 | public class Issue49Tests : Issue49Tests 9 | { 10 | [SetUp] 11 | public override void SetUp() 12 | { 13 | base.SetUp(); 14 | 15 | DbContext = new TestDbContext(new DbContextOptionsBuilder().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Common/QueryRootExpression.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Microsoft.EntityFrameworkCore.Metadata; 4 | using Microsoft.EntityFrameworkCore.Query; 5 | 6 | namespace EntityFrameworkCore.Testing.Common 7 | { 8 | public class FakeQueryRootExpression : EntityQueryRootExpression 9 | { 10 | public FakeQueryRootExpression(IAsyncQueryProvider asyncQueryProvider, IEntityType entityType) : base(asyncQueryProvider, entityType) 11 | { 12 | Type = typeof(IOrderedQueryable<>).MakeGenericType(entityType.ClrType); 13 | } 14 | 15 | public override Type Type { get; } 16 | } 17 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Moq.Tests/DbContextTestsUsingConstructorParameters.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using EntityFrameworkCore.Testing.Common.Tests; 3 | using Microsoft.EntityFrameworkCore; 4 | using NUnit.Framework; 5 | 6 | namespace EntityFrameworkCore.Testing.Moq.Tests 7 | { 8 | public class DbContextTestsUsingConstructorParameters : BaseForDbContextTests 9 | { 10 | [SetUp] 11 | public override void SetUp() 12 | { 13 | base.SetUp(); 14 | 15 | MockedDbContext = Create.MockedDbContextFor(new DbContextOptionsBuilder().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.NSubstitute.Tests/DbContextTestsUsingConstructorParameters.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using EntityFrameworkCore.Testing.Common.Tests; 3 | using Microsoft.EntityFrameworkCore; 4 | using NUnit.Framework; 5 | 6 | namespace EntityFrameworkCore.Testing.NSubstitute.Tests 7 | { 8 | public class DbContextTestsUsingConstructorParameters : BaseForDbContextTests 9 | { 10 | [SetUp] 11 | public override void SetUp() 12 | { 13 | base.SetUp(); 14 | 15 | MockedDbContext = Create.MockedDbContextFor(new DbContextOptionsBuilder().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Moq.Tests/Issue126Tests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using EntityFrameworkCore.Testing.Common.Tests; 3 | using Microsoft.EntityFrameworkCore; 4 | using NUnit.Framework; 5 | 6 | namespace EntityFrameworkCore.Testing.Moq.Tests 7 | { 8 | public class Issue126Tests : Issue126Tests 9 | { 10 | [SetUp] 11 | public override void SetUp() 12 | { 13 | base.SetUp(); 14 | 15 | var options = new DbContextOptionsBuilder() 16 | .UseInMemoryDatabase(Guid.NewGuid().ToString()) 17 | .Options; 18 | 19 | DbContextFactory = () => Create.MockedDbContextFor(options); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Moq.Tests/Issue88Tests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using EntityFrameworkCore.Testing.Common.Tests; 3 | using Microsoft.EntityFrameworkCore; 4 | using NUnit.Framework; 5 | 6 | namespace EntityFrameworkCore.Testing.Moq.Tests 7 | { 8 | public class Issue88Tests : Issue88Tests 9 | { 10 | [SetUp] 11 | public override void SetUp() 12 | { 13 | base.SetUp(); 14 | 15 | var options = new DbContextOptionsBuilder() 16 | .UseInMemoryDatabase(Guid.NewGuid().ToString()) 17 | .Options; 18 | 19 | DbContextFactory = () => Create.MockedDbContextFor(options); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.NSubstitute.Tests/Issue126Tests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using EntityFrameworkCore.Testing.Common.Tests; 3 | using Microsoft.EntityFrameworkCore; 4 | using NUnit.Framework; 5 | 6 | namespace EntityFrameworkCore.Testing.NSubstitute.Tests 7 | { 8 | public class Issue126Tests : Issue126Tests 9 | { 10 | [SetUp] 11 | public override void SetUp() 12 | { 13 | base.SetUp(); 14 | 15 | var options = new DbContextOptionsBuilder() 16 | .UseInMemoryDatabase(Guid.NewGuid().ToString()) 17 | .Options; 18 | 19 | DbContextFactory = () => Create.MockedDbContextFor(options); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Moq.Tests/ByTypeReadOnlyDbSetExceptionTests.cs: -------------------------------------------------------------------------------- 1 | using EntityFrameworkCore.Testing.Common.Tests; 2 | using Microsoft.EntityFrameworkCore; 3 | using NUnit.Framework; 4 | 5 | namespace EntityFrameworkCore.Testing.Moq.Tests 6 | { 7 | public class ByTypeReadOnlyDbSetExceptionTests : ReadOnlyDbSetExceptionTests 8 | { 9 | protected TestDbContext MockedDbContext; 10 | 11 | protected override DbSet DbSet => MockedDbContext.Set(); 12 | 13 | [SetUp] 14 | public override void SetUp() 15 | { 16 | base.SetUp(); 17 | 18 | MockedDbContext = Create.MockedDbContextFor(); 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Moq.Tests/ByPropertyReadOnlyDbSetExceptionTests.cs: -------------------------------------------------------------------------------- 1 | using EntityFrameworkCore.Testing.Common.Tests; 2 | using Microsoft.EntityFrameworkCore; 3 | using NUnit.Framework; 4 | 5 | namespace EntityFrameworkCore.Testing.Moq.Tests 6 | { 7 | public class ByPropertyReadOnlyDbSetExceptionTests : ReadOnlyDbSetExceptionTests 8 | { 9 | protected TestDbContext MockedDbContext; 10 | 11 | protected override DbSet DbSet => MockedDbContext.TestReadOnlyEntities; 12 | 13 | [SetUp] 14 | public override void SetUp() 15 | { 16 | base.SetUp(); 17 | 18 | MockedDbContext = Create.MockedDbContextFor(); 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.NSubstitute.Tests/Issue88Tests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using EntityFrameworkCore.Testing.Common.Tests; 3 | using Microsoft.EntityFrameworkCore; 4 | using NUnit.Framework; 5 | 6 | namespace EntityFrameworkCore.Testing.NSubstitute.Tests 7 | { 8 | public class Issue88Tests : Issue88Tests 9 | { 10 | [SetUp] 11 | public override void SetUp() 12 | { 13 | base.SetUp(); 14 | 15 | var options = new DbContextOptionsBuilder() 16 | .UseInMemoryDatabase(Guid.NewGuid().ToString()) 17 | .Options; 18 | 19 | DbContextFactory = () => Create.MockedDbContextFor(options); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.NSubstitute.Tests/ByTypeReadOnlyDbSetExceptionTests.cs: -------------------------------------------------------------------------------- 1 | using EntityFrameworkCore.Testing.Common.Tests; 2 | using Microsoft.EntityFrameworkCore; 3 | using NUnit.Framework; 4 | 5 | namespace EntityFrameworkCore.Testing.NSubstitute.Tests 6 | { 7 | public class ByTypeReadOnlyDbSetExceptionTests : ReadOnlyDbSetExceptionTests 8 | { 9 | protected TestDbContext MockedDbContext; 10 | 11 | protected override DbSet DbSet => MockedDbContext.Set(); 12 | 13 | [SetUp] 14 | public override void SetUp() 15 | { 16 | base.SetUp(); 17 | 18 | MockedDbContext = Create.MockedDbContextFor(); 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.NSubstitute.Tests/ByPropertyReadOnlyDbSetExceptionTests.cs: -------------------------------------------------------------------------------- 1 | using EntityFrameworkCore.Testing.Common.Tests; 2 | using Microsoft.EntityFrameworkCore; 3 | using NUnit.Framework; 4 | 5 | namespace EntityFrameworkCore.Testing.NSubstitute.Tests 6 | { 7 | public class ByPropertyReadOnlyDbSetExceptionTests : ReadOnlyDbSetExceptionTests 8 | { 9 | protected TestDbContext MockedDbContext; 10 | 11 | protected override DbSet DbSet => MockedDbContext.TestReadOnlyEntities; 12 | 13 | [SetUp] 14 | public override void SetUp() 15 | { 16 | base.SetUp(); 17 | 18 | MockedDbContext = Create.MockedDbContextFor(); 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Common.Tests/BaseForTests.cs: -------------------------------------------------------------------------------- 1 | using AutoFixture; 2 | using Microsoft.Extensions.Logging; 3 | using NUnit.Framework; 4 | using rgvlee.Core.Common.Helpers; 5 | 6 | namespace EntityFrameworkCore.Testing.Common.Tests 7 | { 8 | public abstract class BaseForTests 9 | { 10 | protected Fixture Fixture; 11 | 12 | [SetUp] 13 | public virtual void SetUp() 14 | { 15 | LoggingHelper.LoggerFactory = LoggerFactory.Create(builder => builder.AddConsole().SetMinimumLevel(LogLevel.Trace)); 16 | 17 | Fixture = new Fixture(); 18 | } 19 | 20 | [TearDown] 21 | public virtual void TearDown() 22 | { 23 | LoggingHelper.LoggerFactory.Dispose(); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Common/AsyncEnumerator.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | 4 | namespace EntityFrameworkCore.Testing.Common 5 | { 6 | public class AsyncEnumerator : IAsyncEnumerator 7 | { 8 | private readonly IEnumerator _enumerator; 9 | 10 | public AsyncEnumerator(IEnumerable enumerable) 11 | { 12 | _enumerator = enumerable.GetEnumerator(); 13 | } 14 | 15 | public ValueTask DisposeAsync() 16 | { 17 | return new(); 18 | } 19 | 20 | public ValueTask MoveNextAsync() 21 | { 22 | return new(_enumerator.MoveNext()); 23 | } 24 | 25 | public T Current => _enumerator.Current; 26 | } 27 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Moq/Helpers/MockedDbContextBuilder.cs: -------------------------------------------------------------------------------- 1 | using EntityFrameworkCore.Testing.Common.Helpers; 2 | using Microsoft.EntityFrameworkCore; 3 | 4 | namespace EntityFrameworkCore.Testing.Moq.Helpers 5 | { 6 | /// 7 | /// The mocked db context builder. 8 | /// 9 | /// The db context type. 10 | public class MockedDbContextBuilder : BaseMockedDbContextBuilder where TDbContext : DbContext 11 | { 12 | /// 13 | /// Creates the mocked db context. 14 | /// 15 | /// A mocked db context. 16 | public override TDbContext MockedDbContext => new MockedDbContextFactory(Options).Create(); 17 | } 18 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.NSubstitute/Helpers/MockedDbContextBuilder.cs: -------------------------------------------------------------------------------- 1 | using EntityFrameworkCore.Testing.Common.Helpers; 2 | using Microsoft.EntityFrameworkCore; 3 | 4 | namespace EntityFrameworkCore.Testing.NSubstitute.Helpers 5 | { 6 | /// 7 | /// The mocked db context builder. 8 | /// 9 | /// The db context type. 10 | public class MockedDbContextBuilder : BaseMockedDbContextBuilder where TDbContext : DbContext 11 | { 12 | /// 13 | /// Creates the mocked db context. 14 | /// 15 | /// A mocked db context. 16 | public override TDbContext MockedDbContext => new MockedDbContextFactory(Options).Create(); 17 | } 18 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.DefaultBehaviour.Tests/ByTypeReadOnlyDbSetExceptionTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using EntityFrameworkCore.Testing.Common.Tests; 3 | using Microsoft.EntityFrameworkCore; 4 | using NUnit.Framework; 5 | 6 | namespace EntityFrameworkCore.DefaultBehaviour.Tests 7 | { 8 | public class ReadOnlyDbSetExceptionTests : ReadOnlyDbSetExceptionTests 9 | { 10 | protected TestDbContext DbContext; 11 | 12 | protected override DbSet DbSet => DbContext.Set(); 13 | 14 | [SetUp] 15 | public override void SetUp() 16 | { 17 | base.SetUp(); 18 | 19 | DbContext = new TestDbContext(new DbContextOptionsBuilder().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.DefaultBehaviour.Tests/Issue88Tests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using EntityFrameworkCore.Testing.Common.Tests; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Diagnostics; 5 | using NUnit.Framework; 6 | 7 | namespace EntityFrameworkCore.DefaultBehaviour.Tests 8 | { 9 | public class Issue88Tests : Issue88Tests 10 | { 11 | [SetUp] 12 | public override void SetUp() 13 | { 14 | base.SetUp(); 15 | 16 | var options = new DbContextOptionsBuilder() 17 | .UseInMemoryDatabase(Guid.NewGuid().ToString()) 18 | .ConfigureWarnings(x => x.Ignore(InMemoryEventId.TransactionIgnoredWarning)) 19 | .Options; 20 | 21 | DbContextFactory = () => new TestDbContext(options); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.NSubstitute.Tests/ByTypeDbSetTests.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Linq.Expressions; 3 | using EntityFrameworkCore.Testing.Common.Tests; 4 | using NSubstitute; 5 | using NUnit.Framework; 6 | 7 | namespace EntityFrameworkCore.Testing.NSubstitute.Tests 8 | { 9 | public class ByTypeDbSetTests : BaseForDbSetTests 10 | { 11 | protected override IQueryable Queryable => MockedDbContext.Set(); 12 | 13 | [Test(Description = "This test ensures that method invoked via CallBase = true are verifiable")] 14 | public override void Select_ReturnsSequence() 15 | { 16 | base.Select_ReturnsSequence(); 17 | 18 | Queryable.Provider.Received(2).CreateQuery(Arg.Any()); 19 | 20 | Queryable.Provider.Received(2).CreateQuery(Arg.Is(mce => mce.Method.Name.Equals(nameof(System.Linq.Queryable.Select)))); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Moq/EntityFrameworkCore.Testing.Moq.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net10.0 5 | rgvlee 6 | 7 | 8 | 9 | EntityFrameworkCore.Testing.Moq.xml 10 | NU1605 11 | 12 | 13 | 14 | EntityFrameworkCore.Testing.Moq.xml 15 | true 16 | NU1605 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Common.Tests/AsyncEnumerableTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using AutoFixture; 5 | using NUnit.Framework; 6 | 7 | namespace EntityFrameworkCore.Testing.Common.Tests 8 | { 9 | public class AsyncEnumerableTests : BaseForQueryableTests 10 | { 11 | private IQueryable _source; 12 | 13 | protected override IQueryable Queryable => _source; 14 | 15 | [SetUp] 16 | public override void SetUp() 17 | { 18 | base.SetUp(); 19 | 20 | _source = new AsyncEnumerable(new List()); 21 | } 22 | 23 | protected override void SeedQueryableSource() 24 | { 25 | var itemsToAdd = Fixture.Build().With(p => p.CreatedAt, DateTime.Today).With(p => p.LastModifiedAt, DateTime.Today).CreateMany().ToList(); 26 | _source = new AsyncEnumerable(itemsToAdd); 27 | ItemsAddedToQueryableSource = itemsToAdd; 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.NSubstitute/EntityFrameworkCore.Testing.NSubstitute.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net10.0 5 | rgvlee 6 | 7 | 8 | 9 | EntityFrameworkCore.Testing.NSubstitute.xml 10 | NU1605 11 | 12 | 13 | 14 | EntityFrameworkCore.Testing.NSubstitute.xml 15 | true 16 | NU1605 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Common/Helpers/MockedDbContextFactoryOptions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Microsoft.EntityFrameworkCore; 3 | 4 | namespace EntityFrameworkCore.Testing.Common.Helpers 5 | { 6 | /// 7 | /// The mocked db context factory options. 8 | /// 9 | /// The db context type. 10 | public class MockedDbContextFactoryOptions where TDbContext : DbContext 11 | { 12 | /// 13 | /// The db context instance that the mocked db context will use for in-memory provider supported operations. 14 | /// 15 | public TDbContext DbContext { get; set; } 16 | 17 | /// 18 | /// The parameters that will be used to create the mocked db context and, if one is not provided, 19 | /// the in-memory context that the mocked db context will use for in-memory provider supported operations. 20 | /// 21 | public IEnumerable ConstructorParameters { get; set; } 22 | } 23 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Moq.Tests/ByTypeDbSetTests.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Linq.Expressions; 3 | using EntityFrameworkCore.Testing.Common.Tests; 4 | using Moq; 5 | using NUnit.Framework; 6 | 7 | namespace EntityFrameworkCore.Testing.Moq.Tests 8 | { 9 | public class ByTypeDbSetTests : BaseForDbSetTests 10 | { 11 | protected override IQueryable Queryable => MockedDbContext.Set(); 12 | 13 | [Test(Description = "This test ensures that method invoked via CallBase = true are verifiable")] 14 | public override void Select_ReturnsSequence() 15 | { 16 | base.Select_ReturnsSequence(); 17 | 18 | var queryProviderMock = Mock.Get(Queryable.Provider); 19 | 20 | queryProviderMock.Verify(m => m.CreateQuery(It.IsAny()), Times.Exactly(2)); 21 | 22 | queryProviderMock.Verify(m => m.CreateQuery(It.Is(mce => mce.Method.Name.Equals(nameof(System.Linq.Queryable.Select)))), 23 | Times.Exactly(2)); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Common.Tests/Issue114Tests.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using FluentAssertions; 3 | using Microsoft.EntityFrameworkCore; 4 | using NUnit.Framework; 5 | 6 | namespace EntityFrameworkCore.Testing.Common.Tests 7 | { 8 | public abstract class Issue114Tests : BaseForTests 9 | { 10 | protected abstract TestDbContext MockedDbContextFactory(); 11 | 12 | [Test] 13 | public void Any_ForReadOnlyEntityWithNoDbContextProperty_IsFalse() 14 | { 15 | var mockedContext = MockedDbContextFactory(); 16 | 17 | mockedContext.Set().Any().Should().BeFalse(); 18 | } 19 | 20 | public class TestDbContext : DbContext 21 | { 22 | public TestDbContext(DbContextOptions options) : base(options) { } 23 | 24 | protected override void OnModelCreating(ModelBuilder modelBuilder) 25 | { 26 | modelBuilder.Entity().HasNoKey(); 27 | } 28 | } 29 | 30 | public class Foo 31 | { 32 | public string Bar { get; set; } 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Lee Anderson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Common.Tests/Issue126Tests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using FluentAssertions; 5 | using Microsoft.EntityFrameworkCore; 6 | using NUnit.Framework; 7 | 8 | namespace EntityFrameworkCore.Testing.Common.Tests; 9 | 10 | public abstract class Issue126Tests : BaseForTests where TDbContext : DbContext 11 | { 12 | protected Func DbContextFactory; 13 | 14 | [Test] 15 | public virtual void BeginTransaction_ReturnsMockTransaction() 16 | { 17 | using var transaction = DbContextFactory().Database.BeginTransaction(); 18 | transaction.Should().NotBeNull(); 19 | } 20 | 21 | [TestCase(true)] 22 | [TestCase(false)] 23 | public virtual async Task BeginTransactionAsync_ReturnsMockTransaction(bool withCancellationTokenParameter) 24 | { 25 | await using var transaction = withCancellationTokenParameter 26 | ? await DbContextFactory().Database.BeginTransactionAsync(CancellationToken.None) 27 | : await DbContextFactory().Database.BeginTransactionAsync(); 28 | 29 | transaction.Should().NotBeNull(); 30 | } 31 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.DefaultBehaviour.Tests/EntityFrameworkCore.DefaultBehaviour.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net10.0 5 | false 6 | 7 | 8 | 9 | NU1605 10 | 11 | 12 | 13 | true 14 | NU1605 15 | 16 | 17 | 18 | 19 | 20 | all 21 | runtime; build; native; contentfiles; analyzers; buildtransitive 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Common.Tests/TestDbContext.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.Extensions.Logging; 3 | using rgvlee.Core.Common.Helpers; 4 | 5 | namespace EntityFrameworkCore.Testing.Common.Tests 6 | { 7 | public class TestDbContext : DbContext 8 | { 9 | private static readonly ILogger Logger = LoggingHelper.CreateLogger(); 10 | 11 | public TestDbContext() { } 12 | 13 | public TestDbContext(DbContextOptions options) : base(options) { } 14 | 15 | public TestDbContext(ILogger logger, DbContextOptions options) : base(options) { } 16 | 17 | public virtual DbSet TestEntities { get; set; } 18 | public virtual DbSet TestReadOnlyEntities { get; set; } 19 | 20 | protected override void OnModelCreating(ModelBuilder modelBuilder) 21 | { 22 | modelBuilder.Entity().HasKey(c => c.Id); 23 | 24 | modelBuilder.Entity().HasNoKey().ToView("TestReadOnlyEntities"); 25 | } 26 | 27 | public override int SaveChanges() 28 | { 29 | Logger.LogDebug("SaveChanges invoked"); 30 | return base.SaveChanges(); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Moq/Extensions/QueryProviderExtensions.Internal.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using EntityFrameworkCore.Testing.Common; 4 | using Moq; 5 | using rgvlee.Core.Common.Helpers; 6 | 7 | namespace EntityFrameworkCore.Testing.Moq.Extensions 8 | { 9 | public static partial class QueryProviderExtensions 10 | { 11 | internal static IQueryProvider CreateMockedQueryProvider(this IQueryProvider queryProviderToMock, IEnumerable collection) where T : class 12 | { 13 | EnsureArgument.IsNotNull(queryProviderToMock, nameof(queryProviderToMock)); 14 | EnsureArgument.IsNotNull(collection, nameof(collection)); 15 | 16 | var queryProviderMock = new Mock>(collection); 17 | queryProviderMock.CallBase = true; 18 | return queryProviderMock.Object; 19 | } 20 | 21 | internal static void SetSource(this AsyncQueryProvider mockedQueryProvider, IEnumerable source) where T : class 22 | { 23 | EnsureArgument.IsNotNull(mockedQueryProvider, nameof(mockedQueryProvider)); 24 | EnsureArgument.IsNotNull(source, nameof(source)); 25 | 26 | mockedQueryProvider.Source = source.AsQueryable(); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.NSubstitute/Extensions/QueryProviderExtensions.Internal.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using EntityFrameworkCore.Testing.Common; 4 | using NSubstitute; 5 | using NSubstitute.Extensions; 6 | using rgvlee.Core.Common.Helpers; 7 | 8 | namespace EntityFrameworkCore.Testing.NSubstitute.Extensions 9 | { 10 | public static partial class QueryProviderExtensions 11 | { 12 | internal static IQueryProvider CreateMockedQueryProvider(this IQueryProvider queryProviderToMock, IEnumerable collection) where T : class 13 | { 14 | EnsureArgument.IsNotNull(queryProviderToMock, nameof(queryProviderToMock)); 15 | EnsureArgument.IsNotNull(collection, nameof(collection)); 16 | 17 | var mockedQueryProvider = Substitute.ForPartsOf>(collection); 18 | return mockedQueryProvider; 19 | } 20 | 21 | internal static void SetSource(this AsyncQueryProvider mockedQueryProvider, IEnumerable source) where T : class 22 | { 23 | EnsureArgument.IsNotNull(mockedQueryProvider, nameof(mockedQueryProvider)); 24 | EnsureArgument.IsNotNull(source, nameof(source)); 25 | 26 | mockedQueryProvider.Source = source.AsQueryable(); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | build-and-test: 9 | name: Build, pack and push 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v5 15 | 16 | - name: Setup dotnet 17 | uses: actions/setup-dotnet@v5 18 | with: 19 | dotnet-version: 10.0.x 20 | 21 | - run: sudo apt install mono-devel 22 | 23 | - name: Setup NuGet 24 | uses: nuget/setup-nuget@v2 25 | with: 26 | nuget-version: latest 27 | 28 | - name: Build 29 | run: dotnet build --configuration Release 30 | 31 | - name: Pack 32 | run: | 33 | nuget pack EntityFrameworkCore.Testing.Moq.nuspec -Version ${{ github.event.release.name }} -Symbols -SymbolPackageFormat snupkg 34 | nuget pack EntityFrameworkCore.Testing.NSubstitute.nuspec -Version ${{ github.event.release.name }} -Symbols -SymbolPackageFormat snupkg 35 | 36 | - name: Push 37 | run: | 38 | nuget push EntityFrameworkCore.Testing.Moq*.nupkg -Source https://api.nuget.org/v3/index.json -ApiKey ${{ secrets.NUGET_API_KEY }} 39 | nuget push EntityFrameworkCore.Testing.NSubstitute*.nupkg -Source https://api.nuget.org/v3/index.json -ApiKey ${{ secrets.NUGET_API_KEY }} -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Common.Tests/Issue49Tests.cs: -------------------------------------------------------------------------------- 1 | using AutoFixture; 2 | using FluentAssertions; 3 | using Microsoft.EntityFrameworkCore; 4 | using NUnit.Framework; 5 | 6 | namespace EntityFrameworkCore.Testing.Common.Tests 7 | { 8 | public abstract class Issue49Tests : BaseForTests where TDbContext : DbContext 9 | where TEntity : BaseTestEntity 10 | { 11 | protected TDbContext DbContext; 12 | 13 | [Test] 14 | public virtual void EntityEntryState_Entity_IsDetached() 15 | { 16 | var entity = Fixture.Create(); 17 | 18 | var actualResult = DbContext.Entry(entity).State; 19 | 20 | actualResult.Should().Be(EntityState.Detached); 21 | } 22 | 23 | [Test] 24 | public virtual void EntityEntryState_EntityAsObject_IsDetached() 25 | { 26 | var entity = Fixture.Create(); 27 | 28 | var actualResult = DbContext.Entry((object) entity).State; 29 | 30 | actualResult.Should().Be(EntityState.Detached); 31 | } 32 | 33 | [Test] 34 | public virtual void DbContextAdd_Entity_IsAdded() 35 | { 36 | var entity = Fixture.Create(); 37 | 38 | var actualResult = DbContext.Add(entity); 39 | 40 | actualResult.State.Should().Be(EntityState.Added); 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Common/Helpers/IMockedDbContextBuilder.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | 3 | namespace EntityFrameworkCore.Testing.Common.Helpers 4 | { 5 | /// 6 | /// The mocked db context builder. 7 | /// 8 | /// The db context type. 9 | public interface IMockedDbContextBuilder where TDbContext : DbContext 10 | { 11 | /// 12 | /// The mocked db context. 13 | /// 14 | TDbContext MockedDbContext { get; } 15 | 16 | /// 17 | /// The parameters that will be used to create the mocked db context and, if one is not provided, 18 | /// the in-memory context that the mocked db context will use for in-memory provider supported operations. 19 | /// 20 | /// 21 | /// The constructor parameters. 22 | /// 23 | /// The mocked db context builder. 24 | IMockedDbContextBuilder UseConstructorWithParameters(params object[] constructorParameters); 25 | 26 | /// 27 | /// The db context instance that the mocked db context will use for in-memory provider supported operations. 28 | /// 29 | IMockedDbContextBuilder UseDbContext(TDbContext dbContext); 30 | } 31 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.DefaultBehaviour.Tests/ByTypeReadOnlyDbSetTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using EntityFrameworkCore.Testing.Common.Tests; 4 | using Microsoft.EntityFrameworkCore; 5 | using NUnit.Framework; 6 | 7 | namespace EntityFrameworkCore.DefaultBehaviour.Tests 8 | { 9 | public class ByTypeReadOnlyDbSetTests : BaseForTests 10 | { 11 | protected TestDbContext DbContext; 12 | 13 | protected DbSet DbSet => DbContext.Set(); 14 | 15 | [SetUp] 16 | public override void SetUp() 17 | { 18 | base.SetUp(); 19 | 20 | DbContext = new TestDbContext(new DbContextOptionsBuilder().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options); 21 | } 22 | 23 | [Test] 24 | public virtual void AsAsyncEnumerable_ReturnsAsyncEnumerable() 25 | { 26 | var asyncEnumerable = DbSet.AsAsyncEnumerable(); 27 | 28 | Assert.That(asyncEnumerable, Is.Not.Null); 29 | } 30 | 31 | [Test] 32 | public virtual void AsQueryable_ReturnsQueryable() 33 | { 34 | var queryable = DbSet.AsQueryable(); 35 | 36 | Assert.That(queryable, Is.Not.Null); 37 | } 38 | 39 | [Test] 40 | public void ContainsListCollection_ReturnsFalse() 41 | { 42 | var containsListCollection = ((IListSource) DbSet).ContainsListCollection; 43 | Assert.That(containsListCollection, Is.False); 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Moq.Tests/EntityFrameworkCore.Testing.Moq.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net10.0 5 | false 6 | 7 | 8 | 9 | NU1605 10 | 11 | 12 | 13 | true 14 | NU1605 15 | 16 | 17 | 18 | 19 | runtime; build; native; contentfiles; analyzers; buildtransitive 20 | all 21 | 22 | 23 | 24 | 25 | all 26 | runtime; build; native; contentfiles; analyzers; buildtransitive 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Common/AsyncEnumerable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Linq.Expressions; 6 | using System.Threading; 7 | using Microsoft.EntityFrameworkCore.Query; 8 | 9 | namespace EntityFrameworkCore.Testing.Common 10 | { 11 | public class AsyncEnumerable : IAsyncEnumerable, IOrderedQueryable 12 | { 13 | private readonly IQueryable _source; 14 | 15 | public AsyncEnumerable(IEnumerable enumerable) 16 | { 17 | _source = enumerable.AsQueryable(); 18 | 19 | Provider = new AsyncQueryProvider(_source); 20 | 21 | Expression = _source.Expression; 22 | } 23 | 24 | public AsyncEnumerable(IEnumerable enumerable, QueryRootExpression expression) : this(enumerable) 25 | { 26 | Expression = expression; 27 | } 28 | 29 | public IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = new()) 30 | { 31 | return new AsyncEnumerator(_source); 32 | } 33 | 34 | IEnumerator IEnumerable.GetEnumerator() 35 | { 36 | return _source.GetEnumerator(); 37 | } 38 | 39 | IEnumerator IEnumerable.GetEnumerator() 40 | { 41 | return _source.GetEnumerator(); 42 | } 43 | 44 | public Type ElementType => typeof(T); 45 | 46 | public Expression Expression { get; } 47 | 48 | public IQueryProvider Provider { get; } 49 | } 50 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.NSubstitute.Tests/EntityFrameworkCore.Testing.NSubstitute.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net10.0 5 | false 6 | 7 | 8 | 9 | NU1605 10 | 11 | 12 | 13 | true 14 | NU1605 15 | 16 | 17 | 18 | 19 | runtime; build; native; contentfiles; analyzers; buildtransitive 20 | all 21 | 22 | 23 | 24 | 25 | all 26 | runtime; build; native; contentfiles; analyzers; buildtransitive 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Common/EntityFrameworkCore.Testing.Common.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net10.0 5 | rgvlee 6 | 7 | 8 | 9 | EntityFrameworkCore.Testing.Common.xml 10 | NU1605 11 | 12 | 13 | 14 | EntityFrameworkCore.Testing.Common.xml 15 | true 16 | NU1605 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | True 29 | True 30 | ExceptionMessages.resx 31 | 32 | 33 | 34 | 35 | 36 | PublicResXFileCodeGenerator 37 | ExceptionMessages.Designer.cs 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Moq.Tests/CreateFactoryTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Castle.DynamicProxy; 4 | using EntityFrameworkCore.Testing.Common.Tests; 5 | using Microsoft.EntityFrameworkCore; 6 | using NUnit.Framework; 7 | 8 | namespace EntityFrameworkCore.Testing.Moq.Tests 9 | { 10 | public class CreateFactoryTests : BaseForTests 11 | { 12 | [Test] 13 | public void CreateMockedDbContextFor_Type_CreatesMockedDbContext() 14 | { 15 | var mocked = Create.MockedDbContextFor(); 16 | 17 | Assert.Multiple(() => 18 | { 19 | Assert.That(mocked, Is.Not.Null); 20 | Assert.That(ProxyUtil.IsProxy(mocked), Is.True); 21 | }); 22 | } 23 | 24 | [Test] 25 | public void CreateMockedQueryProviderFor_Queryable_CreatesMockedQueryProvider() 26 | { 27 | var dbContextToMock = new TestDbContext(new DbContextOptionsBuilder().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options); 28 | 29 | var mocked = Create.MockedQueryProviderFor(dbContextToMock.TestEntities); 30 | 31 | Assert.Multiple(() => 32 | { 33 | Assert.That(mocked, Is.Not.Null); 34 | Assert.That(ProxyUtil.IsProxy(mocked), Is.True); 35 | }); 36 | } 37 | 38 | [Test] 39 | public void CreateMockedQueryProviderFor_NullQueryable_ThrowsException() 40 | { 41 | Assert.Throws(() => 42 | { 43 | var mocked = Create.MockedQueryProviderFor((IQueryable) null); 44 | }); 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.NSubstitute.Tests/CreateFactoryTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Castle.DynamicProxy; 4 | using EntityFrameworkCore.Testing.Common.Tests; 5 | using Microsoft.EntityFrameworkCore; 6 | using NUnit.Framework; 7 | 8 | namespace EntityFrameworkCore.Testing.NSubstitute.Tests 9 | { 10 | public class CreateFactoryTests : BaseForTests 11 | { 12 | [Test] 13 | public void CreateMockedDbContextFor_Type_CreatesMockedDbContext() 14 | { 15 | var mocked = Create.MockedDbContextFor(); 16 | 17 | Assert.Multiple(() => 18 | { 19 | Assert.That(mocked, Is.Not.Null); 20 | Assert.That(ProxyUtil.IsProxy(mocked), Is.True); 21 | }); 22 | } 23 | 24 | [Test] 25 | public void CreateMockedQueryProviderFor_Queryable_CreatesMockedQueryProvider() 26 | { 27 | var dbContextToMock = new TestDbContext(new DbContextOptionsBuilder().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options); 28 | 29 | var mocked = Create.MockedQueryProviderFor(dbContextToMock.TestEntities); 30 | 31 | Assert.Multiple(() => 32 | { 33 | Assert.That(mocked, Is.Not.Null); 34 | Assert.That(ProxyUtil.IsProxy(mocked), Is.True); 35 | }); 36 | } 37 | 38 | [Test] 39 | public void CreateMockedQueryProviderFor_NullQueryable_ThrowsException() 40 | { 41 | Assert.Throws(() => 42 | { 43 | var mocked = Create.MockedQueryProviderFor((IQueryable) null); 44 | }); 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Moq.Tests/BaseForDbContextTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using EntityFrameworkCore.Testing.Moq.Extensions; 4 | using Microsoft.EntityFrameworkCore; 5 | 6 | namespace EntityFrameworkCore.Testing.Moq.Tests 7 | { 8 | public abstract class BaseForDbContextTests : Common.Tests.BaseForDbContextTests where T : DbContext 9 | { 10 | public override void AddExecuteSqlInterpolatedResult(T mockedDbContext, int expectedResult) 11 | { 12 | mockedDbContext.AddExecuteSqlInterpolatedResult(expectedResult); 13 | } 14 | 15 | public override void AddExecuteSqlInterpolatedResult(T mockedDbContext, FormattableString sql, int expectedResult) 16 | { 17 | mockedDbContext.AddExecuteSqlInterpolatedResult(sql, expectedResult); 18 | } 19 | 20 | public override void AddExecuteSqlInterpolatedResult(T mockedDbContext, string sql, IEnumerable parameters, int expectedResult) 21 | { 22 | mockedDbContext.AddExecuteSqlInterpolatedResult(sql, parameters, expectedResult); 23 | } 24 | 25 | public override void AddExecuteSqlRawResult(T mockedDbContext, int expectedResult) 26 | { 27 | mockedDbContext.AddExecuteSqlRawResult(expectedResult); 28 | } 29 | 30 | public override void AddExecuteSqlRawResult(T mockedDbContext, string sql, int expectedResult) 31 | { 32 | mockedDbContext.AddExecuteSqlRawResult(sql, expectedResult); 33 | } 34 | 35 | public override void AddExecuteSqlRawResult(T mockedDbContext, string sql, IEnumerable parameters, int expectedResult) 36 | { 37 | mockedDbContext.AddExecuteSqlRawResult(sql, parameters, expectedResult); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.NSubstitute.Tests/BaseForDbContextTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using EntityFrameworkCore.Testing.NSubstitute.Extensions; 4 | using Microsoft.EntityFrameworkCore; 5 | 6 | namespace EntityFrameworkCore.Testing.NSubstitute.Tests 7 | { 8 | public abstract class BaseForDbContextTests : Common.Tests.BaseForDbContextTests where T : DbContext 9 | { 10 | public override void AddExecuteSqlInterpolatedResult(T mockedDbContext, int expectedResult) 11 | { 12 | mockedDbContext.AddExecuteSqlInterpolatedResult(expectedResult); 13 | } 14 | 15 | public override void AddExecuteSqlInterpolatedResult(T mockedDbContext, FormattableString sql, int expectedResult) 16 | { 17 | mockedDbContext.AddExecuteSqlInterpolatedResult(sql, expectedResult); 18 | } 19 | 20 | public override void AddExecuteSqlInterpolatedResult(T mockedDbContext, string sql, IEnumerable parameters, int expectedResult) 21 | { 22 | mockedDbContext.AddExecuteSqlInterpolatedResult(sql, parameters, expectedResult); 23 | } 24 | 25 | public override void AddExecuteSqlRawResult(T mockedDbContext, int expectedResult) 26 | { 27 | mockedDbContext.AddExecuteSqlRawResult(expectedResult); 28 | } 29 | 30 | public override void AddExecuteSqlRawResult(T mockedDbContext, string sql, int expectedResult) 31 | { 32 | mockedDbContext.AddExecuteSqlRawResult(sql, expectedResult); 33 | } 34 | 35 | public override void AddExecuteSqlRawResult(T mockedDbContext, string sql, IEnumerable parameters, int expectedResult) 36 | { 37 | mockedDbContext.AddExecuteSqlRawResult(sql, parameters, expectedResult); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Moq.Tests/BaseForDbSetTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using EntityFrameworkCore.Testing.Common.Tests; 4 | using EntityFrameworkCore.Testing.Moq.Extensions; 5 | using Microsoft.EntityFrameworkCore; 6 | 7 | namespace EntityFrameworkCore.Testing.Moq.Tests 8 | { 9 | public abstract class BaseForDbSetTests : BaseForDbSetTests where T : BaseTestEntity 10 | { 11 | protected override TestDbContext CreateMockedDbContext() 12 | { 13 | return Create.MockedDbContextFor(); 14 | } 15 | 16 | protected override void AddFromSqlRawResult(DbSet mockedDbSet, IEnumerable expectedResult) 17 | { 18 | mockedDbSet.AddFromSqlRawResult(expectedResult); 19 | } 20 | 21 | protected override void AddFromSqlRawResult(DbSet mockedDbSet, string sql, IEnumerable expectedResult) 22 | { 23 | mockedDbSet.AddFromSqlRawResult(sql, expectedResult); 24 | } 25 | 26 | protected override void AddFromSqlRawResult(DbSet mockedDbSet, string sql, IEnumerable parameters, IEnumerable expectedResult) 27 | { 28 | mockedDbSet.AddFromSqlRawResult(sql, parameters, expectedResult); 29 | } 30 | 31 | protected override void AddFromSqlInterpolatedResult(DbSet mockedDbSet, IEnumerable expectedResult) 32 | { 33 | mockedDbSet.AddFromSqlInterpolatedResult(expectedResult); 34 | } 35 | 36 | protected override void AddFromSqlInterpolatedResult(DbSet mockedDbSet, FormattableString sql, IEnumerable expectedResult) 37 | { 38 | mockedDbSet.AddFromSqlInterpolatedResult(sql, expectedResult); 39 | } 40 | 41 | protected override void AddFromSqlInterpolatedResult(DbSet mockedDbSet, string sql, IEnumerable parameters, IEnumerable expectedResult) 42 | { 43 | mockedDbSet.AddFromSqlInterpolatedResult(sql, parameters, expectedResult); 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.NSubstitute.Tests/BaseForDbSetTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using EntityFrameworkCore.Testing.Common.Tests; 4 | using EntityFrameworkCore.Testing.NSubstitute.Extensions; 5 | using Microsoft.EntityFrameworkCore; 6 | 7 | namespace EntityFrameworkCore.Testing.NSubstitute.Tests 8 | { 9 | public abstract class BaseForDbSetTests : BaseForDbSetTests where T : BaseTestEntity 10 | { 11 | protected override TestDbContext CreateMockedDbContext() 12 | { 13 | return Create.MockedDbContextFor(); 14 | } 15 | 16 | protected override void AddFromSqlRawResult(DbSet mockedDbSet, IEnumerable expectedResult) 17 | { 18 | mockedDbSet.AddFromSqlRawResult(expectedResult); 19 | } 20 | 21 | protected override void AddFromSqlRawResult(DbSet mockedDbSet, string sql, IEnumerable expectedResult) 22 | { 23 | mockedDbSet.AddFromSqlRawResult(sql, expectedResult); 24 | } 25 | 26 | protected override void AddFromSqlRawResult(DbSet mockedDbSet, string sql, IEnumerable parameters, IEnumerable expectedResult) 27 | { 28 | mockedDbSet.AddFromSqlRawResult(sql, parameters, expectedResult); 29 | } 30 | 31 | protected override void AddFromSqlInterpolatedResult(DbSet mockedDbSet, IEnumerable expectedResult) 32 | { 33 | mockedDbSet.AddFromSqlInterpolatedResult(expectedResult); 34 | } 35 | 36 | protected override void AddFromSqlInterpolatedResult(DbSet mockedDbSet, FormattableString sql, IEnumerable expectedResult) 37 | { 38 | mockedDbSet.AddFromSqlInterpolatedResult(sql, expectedResult); 39 | } 40 | 41 | protected override void AddFromSqlInterpolatedResult(DbSet mockedDbSet, string sql, IEnumerable parameters, IEnumerable expectedResult) 42 | { 43 | mockedDbSet.AddFromSqlInterpolatedResult(sql, parameters, expectedResult); 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Common.Tests/EntityFrameworkCore.Testing.Common.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net10.0 5 | false 6 | 7 | 8 | 9 | NU1605 10 | 11 | 12 | 13 | true 14 | NU1605 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | runtime; build; native; contentfiles; analyzers; buildtransitive 23 | all 24 | 25 | 26 | 27 | 28 | 29 | 30 | all 31 | runtime; build; native; contentfiles; analyzers; buildtransitive 32 | 33 | 34 | all 35 | runtime; build; native; contentfiles; analyzers; buildtransitive 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Common/Helpers/BaseMockedDbContextBuilder.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using rgvlee.Core.Common.Helpers; 3 | 4 | namespace EntityFrameworkCore.Testing.Common.Helpers 5 | { 6 | /// 7 | /// The mocked db context builder. 8 | /// 9 | /// The db context type. 10 | public abstract class BaseMockedDbContextBuilder : IMockedDbContextBuilder where TDbContext : DbContext 11 | { 12 | /// 13 | /// The create factory options. 14 | /// 15 | protected readonly MockedDbContextFactoryOptions Options = new(); 16 | 17 | /// 18 | /// The mocked db context. 19 | /// 20 | public abstract TDbContext MockedDbContext { get; } 21 | 22 | /// 23 | /// The parameters that will be used to create the mocked db context and, if one is not provided, 24 | /// the in-memory context that the mocked db context will use for in-memory provider supported operations. 25 | /// 26 | /// 27 | /// The constructor parameters. 28 | /// 29 | /// The mocked db context builder. 30 | public IMockedDbContextBuilder UseConstructorWithParameters(params object[] constructorParameters) 31 | { 32 | EnsureArgument.IsNotEmpty(constructorParameters, nameof(constructorParameters)); 33 | Options.ConstructorParameters = constructorParameters; 34 | return this; 35 | } 36 | 37 | /// 38 | /// The db context instance that the mocked db context will use for in-memory provider supported operations. 39 | /// 40 | public IMockedDbContextBuilder UseDbContext(TDbContext dbContext) 41 | { 42 | EnsureArgument.IsNotNull(dbContext, nameof(dbContext)); 43 | Options.DbContext = dbContext; 44 | return this; 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Moq.Tests/Issue1Tests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data; 3 | using Microsoft.Data.SqlClient; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using AutoFixture; 7 | using Castle.DynamicProxy; 8 | using EntityFrameworkCore.Testing.Common.Tests; 9 | using EntityFrameworkCore.Testing.Moq.Extensions; 10 | using Microsoft.EntityFrameworkCore; 11 | using NUnit.Framework; 12 | 13 | namespace EntityFrameworkCore.Testing.Moq.Tests 14 | { 15 | public class Issue1Tests : BaseForTests 16 | { 17 | [Test] 18 | public void CreateMockedDbContextFor_ParametersForSpecificConstructor_CreatesSubstitute() 19 | { 20 | var mockedDbContext = Create.MockedDbContextFor(new DbContextOptionsBuilder().UseInMemoryDatabase(Guid.NewGuid().ToString()) 21 | .EnableSensitiveDataLogging() 22 | .Options); 23 | 24 | Assert.Multiple(() => 25 | { 26 | Assert.That(mockedDbContext, Is.Not.Null); 27 | Assert.That(ProxyUtil.IsProxy(mockedDbContext), Is.True); 28 | }); 29 | } 30 | 31 | [Test] 32 | public async Task ExecuteSqlRawAsync_SpecifiedSqlAndSqlParameter_ReturnsExpectedResultAndSetsOutputParameterValue() 33 | { 34 | var expectedResult = Fixture.Create(); 35 | 36 | var mockedDbContext = Create.MockedDbContextFor(); 37 | mockedDbContext.AddExecuteSqlRawResult(-1, 38 | (sql, parameters) => 39 | { 40 | ((SqlParameter) parameters.ElementAt(0)).Value = expectedResult; 41 | }); 42 | 43 | var outputParameter = new SqlParameter("OutputParameter", SqlDbType.NVarChar, 255) { Direction = ParameterDirection.Output }; 44 | var result = await mockedDbContext.Database.ExecuteSqlRawAsync(@"EXEC [StoredProcedureWithOutputParameter] @OutputParameter = @Result OUTPUT", outputParameter); 45 | 46 | Assert.Multiple(() => 47 | { 48 | Assert.That(result, Is.EqualTo(-1)); 49 | Assert.That(outputParameter.Value.ToString(), Is.EqualTo(expectedResult)); 50 | }); 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Moq.Tests/Issue4Tests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Threading.Tasks; 4 | using AutoFixture; 5 | using EntityFrameworkCore.Testing.Common.Tests; 6 | using Microsoft.EntityFrameworkCore; 7 | using Microsoft.EntityFrameworkCore.Query; 8 | using NUnit.Framework; 9 | 10 | namespace EntityFrameworkCore.Testing.Moq.Tests 11 | { 12 | public class Issue4Tests : BaseForTests 13 | { 14 | [Test] 15 | public void AsQueryable_Set_ReturnsIQueryableOfTWithMockedQueryProvider() 16 | { 17 | var mockedDbContext = Create.MockedDbContextFor(); 18 | 19 | var mockedSetAsQueryable = mockedDbContext.TestEntities.AsQueryable(); 20 | 21 | var asyncProvider = mockedSetAsQueryable.Provider as IAsyncQueryProvider; 22 | Assert.That(asyncProvider, Is.Not.Null); 23 | } 24 | 25 | [Test] 26 | public async Task AsQueryableThenWhereThenSingleOrDefaultAsync_WhereOperationReturnsFalse_ReturnsDefault() 27 | { 28 | var entities = Fixture.CreateMany().ToList(); 29 | var mockedDbContext = Create.MockedDbContextFor(); 30 | var mockedSet = mockedDbContext.TestEntities; 31 | mockedSet.AddRange(entities); 32 | mockedDbContext.SaveChanges(); 33 | 34 | var result = await mockedSet.AsQueryable().Where(x => x.Id.Equals(Guid.NewGuid())).SingleOrDefaultAsync(); 35 | 36 | Assert.That(result, Is.Null); 37 | } 38 | 39 | [Test] 40 | public async Task AsQueryableThenWhereThenSingleOrDefaultAsync_WhereOperationReturnsTrue_ReturnsSingleEntity() 41 | { 42 | var entities = Fixture.CreateMany().ToList(); 43 | var entityToFind = entities.ElementAt(1); 44 | var mockedDbContext = Create.MockedDbContextFor(); 45 | var mockedSet = mockedDbContext.TestEntities; 46 | mockedSet.AddRange(entities); 47 | mockedDbContext.SaveChanges(); 48 | 49 | var result = await mockedSet.AsQueryable().Where(x => x.Id.Equals(entityToFind.Id)).SingleOrDefaultAsync(); 50 | 51 | Assert.That(result, Is.EqualTo(entityToFind)); 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.NSubstitute.Tests/Issue1Tests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data; 3 | using Microsoft.Data.SqlClient; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using AutoFixture; 7 | using Castle.DynamicProxy; 8 | using EntityFrameworkCore.Testing.Common.Tests; 9 | using EntityFrameworkCore.Testing.NSubstitute.Extensions; 10 | using Microsoft.EntityFrameworkCore; 11 | using NUnit.Framework; 12 | 13 | namespace EntityFrameworkCore.Testing.NSubstitute.Tests 14 | { 15 | public class Issue1Tests : BaseForTests 16 | { 17 | [Test] 18 | public void CreateMockedDbContextFor_ParametersForSpecificConstructor_CreatesSubstitute() 19 | { 20 | var mockedDbContext = Create.MockedDbContextFor(new DbContextOptionsBuilder().UseInMemoryDatabase(Guid.NewGuid().ToString()) 21 | .EnableSensitiveDataLogging() 22 | .Options); 23 | 24 | Assert.Multiple(() => 25 | { 26 | Assert.That(mockedDbContext, Is.Not.Null); 27 | Assert.That(ProxyUtil.IsProxy(mockedDbContext), Is.True); 28 | }); 29 | } 30 | 31 | [Test] 32 | public async Task ExecuteSqlRawAsync_SpecifiedSqlAndSqlParameter_ReturnsExpectedResultAndSetsOutputParameterValue() 33 | { 34 | var expectedResult = Fixture.Create(); 35 | 36 | var mockedDbContext = Create.MockedDbContextFor(); 37 | mockedDbContext.AddExecuteSqlRawResult(-1, 38 | (sql, parameters) => 39 | { 40 | ((SqlParameter) parameters.ElementAt(0)).Value = expectedResult; 41 | }); 42 | 43 | var outputParameter = new SqlParameter("OutputParameter", SqlDbType.NVarChar, 255) { Direction = ParameterDirection.Output }; 44 | var result = await mockedDbContext.Database.ExecuteSqlRawAsync(@"EXEC [StoredProcedureWithOutputParameter] @OutputParameter = @Result OUTPUT", outputParameter); 45 | 46 | Assert.Multiple(() => 47 | { 48 | Assert.That(result, Is.EqualTo(-1)); 49 | Assert.That(outputParameter.Value.ToString(), Is.EqualTo(expectedResult)); 50 | }); 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Common.Tests/Issue117Tests.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using AutoFixture; 3 | using FluentAssertions; 4 | using Microsoft.EntityFrameworkCore; 5 | using NUnit.Framework; 6 | using static FluentAssertions.FluentActions; 7 | 8 | namespace EntityFrameworkCore.Testing.Common.Tests 9 | { 10 | public abstract class Issue117Tests : BaseForTests 11 | { 12 | protected abstract TestDbContext MockedDbContextFactory(); 13 | 14 | [Test] 15 | public void DbContextDispose_InvokedViaUsingBlock_DoesNotThrowException() 16 | { 17 | Invoking(() => 18 | { 19 | using (MockedDbContextFactory()) { } 20 | }).Should().NotThrow(); 21 | } 22 | 23 | [Test] 24 | public void DbContextDispose_DoesNotThrowException() 25 | { 26 | Invoking(() => MockedDbContextFactory().Dispose()).Should().NotThrow(); 27 | } 28 | 29 | [Test] 30 | public void DbContextAddRange_DoesNotThrowException() 31 | { 32 | Invoking(() => MockedDbContextFactory().AddRange(Fixture.CreateMany())).Should().NotThrow(); 33 | } 34 | 35 | [Test] 36 | public void DbContextAddRangeThenSaveChanges_WithinUsingBlock_PersistsMutableEntities() 37 | { 38 | using (var dbContext = MockedDbContextFactory()) 39 | { 40 | var entities = Fixture.CreateMany(); 41 | 42 | dbContext.AddRange(entities); 43 | dbContext.SaveChanges(); 44 | 45 | dbContext.Set().ToList().Should().BeEquivalentTo(entities); 46 | } 47 | } 48 | 49 | public class TestDbContext : DbContext 50 | { 51 | public TestDbContext(DbContextOptions options) : base(options) { } 52 | 53 | public virtual DbSet MutableEntities { get; set; } 54 | 55 | protected override void OnModelCreating(ModelBuilder modelBuilder) 56 | { 57 | modelBuilder.Entity().HasKey(c => c.Id); 58 | } 59 | } 60 | 61 | public class Foo 62 | { 63 | public string Id { get; set; } 64 | 65 | public string Bar { get; set; } 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.NSubstitute.Tests/Issue4Tests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Threading.Tasks; 4 | using AutoFixture; 5 | using EntityFrameworkCore.Testing.Common.Tests; 6 | using Microsoft.EntityFrameworkCore; 7 | using Microsoft.EntityFrameworkCore.Query; 8 | using NUnit.Framework; 9 | 10 | namespace EntityFrameworkCore.Testing.NSubstitute.Tests 11 | { 12 | public class Issue4Tests : BaseForTests 13 | { 14 | [Test] 15 | public void AsQueryable_Set_ReturnsIQueryableOfTWithMockedQueryProvider() 16 | { 17 | var mockedDbContext = Create.MockedDbContextFor(); 18 | 19 | var mockedSetAsQueryable = mockedDbContext.TestEntities.AsQueryable(); 20 | 21 | var asyncProvider = mockedSetAsQueryable.Provider as IAsyncQueryProvider; 22 | Assert.That(asyncProvider, Is.Not.Null); 23 | } 24 | 25 | [Test] 26 | public async Task AsQueryableThenWhereThenSingleOrDefaultAsync_WhereOperationReturnsFalse_ReturnsDefault() 27 | { 28 | var entities = Fixture.CreateMany().ToList(); 29 | var mockedDbContext = Create.MockedDbContextFor(); 30 | var mockedSet = mockedDbContext.TestEntities; 31 | mockedSet.AddRange(entities); 32 | mockedDbContext.SaveChanges(); 33 | 34 | var result = await mockedSet.AsQueryable().Where(x => x.Id.Equals(Guid.NewGuid())).SingleOrDefaultAsync(); 35 | 36 | Assert.That(result, Is.Null); 37 | } 38 | 39 | [Test] 40 | public async Task AsQueryableThenWhereThenSingleOrDefaultAsync_WhereOperationReturnsTrue_ReturnsSingleEntity() 41 | { 42 | var entities = Fixture.CreateMany().ToList(); 43 | var entityToFind = entities.ElementAt(1); 44 | var mockedDbContext = Create.MockedDbContextFor(); 45 | var mockedSet = mockedDbContext.TestEntities; 46 | mockedSet.AddRange(entities); 47 | mockedDbContext.SaveChanges(); 48 | 49 | var result = await mockedSet.AsQueryable().Where(x => x.Id.Equals(entityToFind.Id)).SingleOrDefaultAsync(); 50 | 51 | Assert.That(result, Is.EqualTo(entityToFind)); 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Common.Tests/Issue88Tests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using AutoFixture; 4 | using FluentAssertions; 5 | using Microsoft.EntityFrameworkCore; 6 | using NUnit.Framework; 7 | 8 | namespace EntityFrameworkCore.Testing.Common.Tests 9 | { 10 | public abstract class Issue88Tests : BaseForTests where TDbContext : DbContext 11 | where TEntity : BaseTestEntity 12 | { 13 | protected Func DbContextFactory; 14 | 15 | [Test] 16 | public virtual void AddThenSaveChanges_ChangesVisibleAnyDbContext() 17 | { 18 | var entity = Fixture.Create(); 19 | 20 | var dbContext = DbContextFactory(); 21 | 22 | dbContext.Set().Add(entity); 23 | dbContext.SaveChanges(); 24 | 25 | dbContext.Find(entity.Id).Should().BeEquivalentTo(entity); 26 | dbContext.Set().Single(x => x.Id.Equals(entity.Id)).Should().BeEquivalentTo(entity); 27 | 28 | var anotherDbContext = DbContextFactory(); 29 | anotherDbContext.Find(entity.Id).Should().BeEquivalentTo(entity); 30 | anotherDbContext.Set().Single(x => x.Id.Equals(entity.Id)).Should().BeEquivalentTo(entity); 31 | } 32 | 33 | [Test] 34 | public virtual void BeginTransactionThenAddThenSaveChangesThenCommit_ChangesVisibleAnyDbContext() 35 | { 36 | var entity = Fixture.Create(); 37 | 38 | var dbContext = DbContextFactory(); 39 | 40 | using (var transaction = dbContext.Database.BeginTransaction()) 41 | { 42 | dbContext.Set().Add(entity); 43 | dbContext.SaveChanges(); 44 | transaction.Commit(); 45 | } 46 | 47 | dbContext.Find(entity.Id).Should().BeEquivalentTo(entity); 48 | dbContext.Set().Single(x => x.Id.Equals(entity.Id)).Should().BeEquivalentTo(entity); 49 | 50 | var anotherDbContext = DbContextFactory(); 51 | anotherDbContext.Find(entity.Id).Should().BeEquivalentTo(entity); 52 | anotherDbContext.Set().Single(x => x.Id.Equals(entity.Id)).Should().BeEquivalentTo(entity); 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Moq/Create.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using EntityFrameworkCore.Testing.Moq.Extensions; 3 | using EntityFrameworkCore.Testing.Moq.Helpers; 4 | using Microsoft.EntityFrameworkCore; 5 | using rgvlee.Core.Common.Helpers; 6 | 7 | namespace EntityFrameworkCore.Testing.Moq 8 | { 9 | /// 10 | /// Factory for creating mocked instances. 11 | /// 12 | public static class Create 13 | { 14 | /// 15 | /// Creates a mocked db context. 16 | /// 17 | /// The db context type. 18 | /// 19 | /// The parameters that will be used to create the mocked db context and, if one is not provided, 20 | /// the in-memory context that the mocked db context will use for in-memory provider supported operations. 21 | /// 22 | /// A mocked db context. 23 | /// 24 | /// If you do not provide any constructor arguments this method attempt to create a TDbContext 25 | /// via a constructor with a single DbContextOptionsBuilder parameter or a parameterless constructor. 26 | /// 27 | public static TDbContext MockedDbContextFor(params object[] constructorParameters) where TDbContext : DbContext 28 | { 29 | return constructorParameters != null && constructorParameters.Any() 30 | ? new MockedDbContextBuilder().UseConstructorWithParameters(constructorParameters).MockedDbContext 31 | : new MockedDbContextBuilder().MockedDbContext; 32 | } 33 | 34 | /// 35 | /// Creates a mocked query provider. 36 | /// 37 | /// The queryable type. 38 | /// The query provider source. 39 | /// A mocked query provider. 40 | public static IQueryProvider MockedQueryProviderFor(IQueryable queryable) where T : class 41 | { 42 | EnsureArgument.IsNotNull(queryable, nameof(queryable)); 43 | 44 | return queryable.Provider.CreateMockedQueryProvider(queryable); 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.NSubstitute/Create.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using EntityFrameworkCore.Testing.NSubstitute.Extensions; 3 | using EntityFrameworkCore.Testing.NSubstitute.Helpers; 4 | using Microsoft.EntityFrameworkCore; 5 | using rgvlee.Core.Common.Helpers; 6 | 7 | namespace EntityFrameworkCore.Testing.NSubstitute 8 | { 9 | /// 10 | /// Factory for creating mocked instances. 11 | /// 12 | public static class Create 13 | { 14 | /// 15 | /// Creates a mocked db context. 16 | /// 17 | /// The db context type. 18 | /// 19 | /// The parameters that will be used to create the mocked db context and, if one is not provided, 20 | /// the in-memory context that the mocked db context will use for in-memory provider supported operations. 21 | /// 22 | /// A mocked db context. 23 | /// 24 | /// If you do not provide any constructor arguments this method attempt to create a TDbContext 25 | /// via a constructor with a single DbContextOptionsBuilder parameter or a parameterless constructor. 26 | /// 27 | public static TDbContext MockedDbContextFor(params object[] constructorParameters) where TDbContext : DbContext 28 | { 29 | return constructorParameters != null && constructorParameters.Any() 30 | ? new MockedDbContextBuilder().UseConstructorWithParameters(constructorParameters).MockedDbContext 31 | : new MockedDbContextBuilder().MockedDbContext; 32 | } 33 | 34 | /// 35 | /// Creates a mocked query provider. 36 | /// 37 | /// The queryable type. 38 | /// The query provider source. 39 | /// A mocked query provider. 40 | public static IQueryProvider MockedQueryProviderFor(IQueryable queryable) where T : class 41 | { 42 | EnsureArgument.IsNotNull(queryable, nameof(queryable)); 43 | 44 | return queryable.Provider.CreateMockedQueryProvider(queryable); 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.DefaultBehaviour.Tests/DbContextTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using EntityFrameworkCore.Testing.Common; 4 | using EntityFrameworkCore.Testing.Common.Tests; 5 | using Microsoft.EntityFrameworkCore; 6 | using NUnit.Framework; 7 | 8 | namespace EntityFrameworkCore.DefaultBehaviour.Tests 9 | { 10 | public class DbContextTests : BaseForTests 11 | { 12 | protected TestDbContext DbContext; 13 | 14 | [SetUp] 15 | public override void SetUp() 16 | { 17 | base.SetUp(); 18 | 19 | DbContext = new TestDbContext(new DbContextOptionsBuilder().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options); 20 | } 21 | 22 | [Test] 23 | public virtual void ExecuteSqlInterpolated_ThrowsException() 24 | { 25 | Assert.Throws(() => 26 | { 27 | var actualResult = DbContext.Database.ExecuteSqlInterpolated($"sp_NoParams"); 28 | }); 29 | } 30 | 31 | [Test] 32 | public virtual void ExecuteSqlRaw_ThrowsException() 33 | { 34 | Assert.Throws(() => 35 | { 36 | var actualResult = DbContext.Database.ExecuteSqlRaw("sp_NoParams"); 37 | }); 38 | } 39 | 40 | [Test] 41 | public virtual void Set_TypeNotIncludedInModel_ThrowsException() 42 | { 43 | Assert.Multiple(() => 44 | { 45 | var ex = Assert.Throws(() => DbContext.Set().ToList()); 46 | Assert.That(ex.Message, Is.EqualTo(string.Format(ExceptionMessages.CannotCreateDbSetTypeNotIncludedInModel, nameof(NotRegisteredEntity)))); 47 | }); 48 | } 49 | 50 | [Test] 51 | public virtual void SetCommandTimeout_ValidTimeout_ThrowsException() 52 | { 53 | Assert.Throws(() => 54 | { 55 | DbContext.Database.SetCommandTimeout(60); 56 | }); 57 | } 58 | 59 | [Test] 60 | public virtual void GetCommandTimeout_ThrowsException() 61 | { 62 | Assert.Throws(() => 63 | { 64 | DbContext.Database.GetCommandTimeout(); 65 | }); 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Moq.Tests/Issue6Tests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using AutoFixture; 4 | using EntityFrameworkCore.Testing.Common.Tests; 5 | using EntityFrameworkCore.Testing.Moq.Extensions; 6 | using Microsoft.EntityFrameworkCore; 7 | using NUnit.Framework; 8 | 9 | namespace EntityFrameworkCore.Testing.Moq.Tests 10 | { 11 | public class Issue6Tests : BaseForTests 12 | { 13 | private static IEnumerable FromSqlInterpolated_SpecifiedSqlWithNullParameters_TestCases { 14 | get 15 | { 16 | yield return new TestCaseData(null, null); 17 | yield return new TestCaseData(null, 1); 18 | yield return new TestCaseData(DateTime.Parse("21 May 2020 9:05 PM"), null); 19 | } 20 | } 21 | 22 | [TestCaseSource(nameof(FromSqlInterpolated_SpecifiedSqlWithNullParameters_TestCases))] 23 | public void FromSqlInterpolated_SpecifiedSqlWithNullParameters_ReturnsExpectedResult(DateTime? dateTimeValue, int? intValue) 24 | { 25 | var expectedResult = new List { Fixture.Create() }; 26 | 27 | var mockedDbContext = Create.MockedDbContextFor(); 28 | mockedDbContext.Set().AddFromSqlInterpolatedResult($"SELECT * FROM [SqlFunctionWithNullableParameters]({dateTimeValue}, {intValue})", expectedResult); 29 | 30 | var actualResult = mockedDbContext.Set().FromSqlInterpolated($"SELECT * FROM [SqlFunctionWithNullableParameters]({dateTimeValue}, {intValue})"); 31 | 32 | Assert.That(actualResult, Is.EqualTo(expectedResult)); 33 | } 34 | 35 | [Test] 36 | public void FromSqlInterpolated_SpecifiedSqlWithDbNullParameters_ReturnsExpectedResult() 37 | { 38 | var expectedResult = new List { Fixture.Create() }; 39 | 40 | var mockedDbContext = Create.MockedDbContextFor(); 41 | mockedDbContext.Set().AddFromSqlInterpolatedResult($"SELECT * FROM [SqlFunctionWithNullableParameters]({DBNull.Value}, {DBNull.Value})", expectedResult); 42 | 43 | var actualResult = mockedDbContext.Set().FromSqlInterpolated($"SELECT * FROM [SqlFunctionWithNullableParameters]({DBNull.Value}, {DBNull.Value})"); 44 | 45 | Assert.That(actualResult, Is.EqualTo(expectedResult)); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /.github/workflows/continuous-integration-checks.yml: -------------------------------------------------------------------------------- 1 | name: Continuous Integration Checks 2 | 3 | on: 4 | push: 5 | schedule: 6 | - cron: "0 9 * * 3" 7 | 8 | jobs: 9 | build-and-test: 10 | name: Build and test 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v5 16 | 17 | - name: Setup dotnet 18 | uses: actions/setup-dotnet@v5 19 | with: 20 | dotnet-version: 10.0.x 21 | 22 | - name: Build 23 | run: dotnet build --configuration Release 24 | 25 | # - name: List dependencies 26 | # run: dotnet list EntityFrameworkCore.Testing.sln package 27 | 28 | - name: Test 29 | run: dotnet test --configuration Release --no-build /p:CollectCoverage=\"true\" /p:Exclude=\"[*.Tests]*,[rgvlee.Core.*]*\" /p:SkipAutoProps=\"false\" /p:IncludeTestAssembly=\"false\" /p:CoverletOutput=\"../../CoverageResults/\" /p:MergeWith=\"../../CoverageResults/coverage.json\" /p:CoverletOutputFormat=\"opencover,json\" -m:1 30 | 31 | - name: Update dependencies 32 | run: | 33 | dotnet add src/EntityFrameworkCore.Testing.Common package Microsoft.EntityFrameworkCore.InMemory --version 10.*-* 34 | dotnet add src/EntityFrameworkCore.Testing.Common package Microsoft.EntityFrameworkCore.Relational --version 10.*-* 35 | dotnet add src/EntityFrameworkCore.Testing.Common package Microsoft.Extensions.Logging --version 10.*-* 36 | dotnet add src/EntityFrameworkCore.Testing.Common package rgvlee.Core 37 | 38 | dotnet add src/EntityFrameworkCore.Testing.Common.Tests package Microsoft.Extensions.Logging.Console --version 10.*-* 39 | 40 | dotnet add src/EntityFrameworkCore.Testing.Moq package Moq 41 | 42 | dotnet add src/EntityFrameworkCore.Testing.NSubstitute package NSubstitute 43 | 44 | # - name: List dependencies 45 | # run: dotnet list EntityFrameworkCore.Testing.sln package 46 | 47 | - name: Test with updated dependencies 48 | run: dotnet test --configuration Release /p:CollectCoverage=\"false\" /p:Exclude=\"[*.Tests]*,[rgvlee.Core.*]*\" /p:SkipAutoProps=\"false\" /p:IncludeTestAssembly=\"false\" -m:1 49 | 50 | - name: Send coverage results to Codacy 51 | uses: codacy/codacy-coverage-reporter-action@master 52 | with: 53 | project-token: ${{ secrets.CODACY_PROJECT_TOKEN }} 54 | coverage-reports: ./CoverageResults/coverage.*opencover.xml -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.NSubstitute.Tests/Issue6Tests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using AutoFixture; 4 | using EntityFrameworkCore.Testing.Common.Tests; 5 | using EntityFrameworkCore.Testing.NSubstitute.Extensions; 6 | using Microsoft.EntityFrameworkCore; 7 | using NUnit.Framework; 8 | 9 | namespace EntityFrameworkCore.Testing.NSubstitute.Tests 10 | { 11 | public class Issue6Tests : BaseForTests 12 | { 13 | private static IEnumerable FromSqlInterpolated_SpecifiedSqlWithNullParameters_TestCases { 14 | get 15 | { 16 | yield return new TestCaseData(null, null); 17 | yield return new TestCaseData(null, 1); 18 | yield return new TestCaseData(DateTime.Parse("21 May 2020 9:05 PM"), null); 19 | } 20 | } 21 | 22 | [TestCaseSource(nameof(FromSqlInterpolated_SpecifiedSqlWithNullParameters_TestCases))] 23 | public void FromSqlInterpolated_SpecifiedSqlWithNullParameters_ReturnsExpectedResult(DateTime? dateTimeValue, int? intValue) 24 | { 25 | var expectedResult = new List { Fixture.Create() }; 26 | 27 | var mockedDbContext = Create.MockedDbContextFor(); 28 | mockedDbContext.Set().AddFromSqlInterpolatedResult($"SELECT * FROM [SqlFunctionWithNullableParameters]({dateTimeValue}, {intValue})", expectedResult); 29 | 30 | var actualResult = mockedDbContext.Set().FromSqlInterpolated($"SELECT * FROM [SqlFunctionWithNullableParameters]({dateTimeValue}, {intValue})"); 31 | 32 | Assert.That(actualResult, Is.EqualTo(expectedResult)); 33 | } 34 | 35 | [Test] 36 | public void FromSqlInterpolated_SpecifiedSqlWithDbNullParameters_ReturnsExpectedResult() 37 | { 38 | var expectedResult = new List { Fixture.Create() }; 39 | 40 | var mockedDbContext = Create.MockedDbContextFor(); 41 | mockedDbContext.Set().AddFromSqlInterpolatedResult($"SELECT * FROM [SqlFunctionWithNullableParameters]({DBNull.Value}, {DBNull.Value})", expectedResult); 42 | 43 | var actualResult = mockedDbContext.Set().FromSqlInterpolated($"SELECT * FROM [SqlFunctionWithNullableParameters]({DBNull.Value}, {DBNull.Value})"); 44 | 45 | Assert.That(actualResult, Is.EqualTo(expectedResult)); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Moq.Tests/BaseForDbQueryTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using EntityFrameworkCore.Testing.Common.Tests; 4 | using EntityFrameworkCore.Testing.Moq.Extensions; 5 | using Microsoft.EntityFrameworkCore; 6 | using NUnit.Framework; 7 | 8 | namespace EntityFrameworkCore.Testing.Moq.Tests 9 | { 10 | public abstract class BaseForDbQueryTests : BaseForReadOnlyDbSetTests where T : BaseTestEntity 11 | { 12 | protected TestDbContext MockedDbContext; 13 | 14 | [SetUp] 15 | public override void SetUp() 16 | { 17 | base.SetUp(); 18 | 19 | MockedDbContext = Create.MockedDbContextFor(); 20 | } 21 | 22 | protected override void AddFromSqlRawResult(DbSet mockedDbSet, IEnumerable expectedResult) 23 | { 24 | mockedDbSet.AddFromSqlRawResult(expectedResult); 25 | } 26 | 27 | protected override void AddFromSqlRawResult(DbSet mockedDbSet, string sql, IEnumerable expectedResult) 28 | { 29 | mockedDbSet.AddFromSqlRawResult(sql, expectedResult); 30 | } 31 | 32 | protected override void AddFromSqlRawResult(DbSet mockedDbSet, string sql, IEnumerable parameters, IEnumerable expectedResult) 33 | { 34 | mockedDbSet.AddFromSqlRawResult(sql, parameters, expectedResult); 35 | } 36 | 37 | protected override void AddFromSqlInterpolatedResult(DbSet mockedDbSet, IEnumerable expectedResult) 38 | { 39 | mockedDbSet.AddFromSqlInterpolatedResult(expectedResult); 40 | } 41 | 42 | protected override void AddFromSqlInterpolatedResult(DbSet mockedDbSet, FormattableString sql, IEnumerable expectedResult) 43 | { 44 | mockedDbSet.AddFromSqlInterpolatedResult(sql, expectedResult); 45 | } 46 | 47 | protected override void AddFromSqlInterpolatedResult(DbSet mockedDbSet, string sql, IEnumerable parameters, IEnumerable expectedResult) 48 | { 49 | mockedDbSet.AddFromSqlInterpolatedResult(sql, parameters, expectedResult); 50 | } 51 | 52 | protected override void AddToReadOnlySource(DbSet mockedDbQuery, T item) 53 | { 54 | mockedDbQuery.AddToReadOnlySource(item); 55 | } 56 | 57 | protected override void AddRangeToReadOnlySource(DbSet mockedDbQuery, IEnumerable items) 58 | { 59 | mockedDbQuery.AddRangeToReadOnlySource(items); 60 | } 61 | 62 | protected override void ClearReadOnlySource(DbSet mockedDbQuery) 63 | { 64 | mockedDbQuery.ClearReadOnlySource(); 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.NSubstitute.Tests/BaseForDbQueryTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using EntityFrameworkCore.Testing.Common.Tests; 4 | using EntityFrameworkCore.Testing.NSubstitute.Extensions; 5 | using Microsoft.EntityFrameworkCore; 6 | using NUnit.Framework; 7 | 8 | namespace EntityFrameworkCore.Testing.NSubstitute.Tests 9 | { 10 | public abstract class BaseForDbQueryTests : BaseForReadOnlyDbSetTests where T : BaseTestEntity 11 | { 12 | protected TestDbContext MockedDbContext; 13 | 14 | [SetUp] 15 | public override void SetUp() 16 | { 17 | base.SetUp(); 18 | 19 | MockedDbContext = Create.MockedDbContextFor(); 20 | } 21 | 22 | protected override void AddFromSqlRawResult(DbSet mockedDbSet, IEnumerable expectedResult) 23 | { 24 | mockedDbSet.AddFromSqlRawResult(expectedResult); 25 | } 26 | 27 | protected override void AddFromSqlRawResult(DbSet mockedDbSet, string sql, IEnumerable expectedResult) 28 | { 29 | mockedDbSet.AddFromSqlRawResult(sql, expectedResult); 30 | } 31 | 32 | protected override void AddFromSqlRawResult(DbSet mockedDbSet, string sql, IEnumerable parameters, IEnumerable expectedResult) 33 | { 34 | mockedDbSet.AddFromSqlRawResult(sql, parameters, expectedResult); 35 | } 36 | 37 | protected override void AddFromSqlInterpolatedResult(DbSet mockedDbSet, IEnumerable expectedResult) 38 | { 39 | mockedDbSet.AddFromSqlInterpolatedResult(expectedResult); 40 | } 41 | 42 | protected override void AddFromSqlInterpolatedResult(DbSet mockedDbSet, FormattableString sql, IEnumerable expectedResult) 43 | { 44 | mockedDbSet.AddFromSqlInterpolatedResult(sql, expectedResult); 45 | } 46 | 47 | protected override void AddFromSqlInterpolatedResult(DbSet mockedDbSet, string sql, IEnumerable parameters, IEnumerable expectedResult) 48 | { 49 | mockedDbSet.AddFromSqlInterpolatedResult(sql, parameters, expectedResult); 50 | } 51 | 52 | protected override void AddToReadOnlySource(DbSet mockedDbQuery, T item) 53 | { 54 | mockedDbQuery.AddToReadOnlySource(item); 55 | } 56 | 57 | protected override void AddRangeToReadOnlySource(DbSet mockedDbQuery, IEnumerable items) 58 | { 59 | mockedDbQuery.AddRangeToReadOnlySource(items); 60 | } 61 | 62 | protected override void ClearReadOnlySource(DbSet mockedDbQuery) 63 | { 64 | mockedDbQuery.ClearReadOnlySource(); 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Moq/Extensions/ReadOnlyDbSetExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using Microsoft.EntityFrameworkCore; 4 | using rgvlee.Core.Common.Helpers; 5 | 6 | namespace EntityFrameworkCore.Testing.Moq.Extensions 7 | { 8 | /// 9 | /// Extensions for read-only db sets. 10 | /// 11 | public static partial class ReadOnlyDbSetExtensions 12 | { 13 | /// 14 | /// Adds an item to the end of the mocked readonly db set source. 15 | /// 16 | /// The entity type. 17 | /// The mocked readonly db set. 18 | /// The item to be added to the end of the mocked readonly db set source. 19 | public static void AddToReadOnlySource(this DbSet mockedReadOnlyDbSet, TEntity item) where TEntity : class 20 | { 21 | EnsureArgument.IsNotNull(mockedReadOnlyDbSet, nameof(mockedReadOnlyDbSet)); 22 | EnsureArgument.IsNotNull(item, nameof(item)); 23 | 24 | var list = mockedReadOnlyDbSet.ToList(); 25 | list.Add(item); 26 | 27 | mockedReadOnlyDbSet.SetSource(list); 28 | } 29 | 30 | /// 31 | /// Adds the items of the specified sequence to the end of the mocked readonly db set source. 32 | /// 33 | /// The entity type. 34 | /// The mocked readonly db set. 35 | /// The sequence whose items should be added to the end of the mocked readonly db set source. 36 | public static void AddRangeToReadOnlySource(this DbSet mockedReadOnlyDbSet, IEnumerable items) where TEntity : class 37 | { 38 | EnsureArgument.IsNotNull(mockedReadOnlyDbSet, nameof(mockedReadOnlyDbSet)); 39 | EnsureArgument.IsNotEmpty(items, nameof(items)); 40 | 41 | var list = mockedReadOnlyDbSet.ToList(); 42 | list.AddRange(items); 43 | 44 | mockedReadOnlyDbSet.SetSource(list); 45 | } 46 | 47 | /// 48 | /// Removes all items from the mocked readonly db set source. 49 | /// 50 | /// The entity type. 51 | /// The mocked readonly db set. 52 | public static void ClearReadOnlySource(this DbSet mockedReadOnlyDbSet) where TEntity : class 53 | { 54 | EnsureArgument.IsNotNull(mockedReadOnlyDbSet, nameof(mockedReadOnlyDbSet)); 55 | mockedReadOnlyDbSet.SetSource(new List()); 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.NSubstitute/Extensions/ReadOnlyDbSetExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using Microsoft.EntityFrameworkCore; 4 | using rgvlee.Core.Common.Helpers; 5 | 6 | namespace EntityFrameworkCore.Testing.NSubstitute.Extensions 7 | { 8 | /// 9 | /// Extensions for read-only db sets. 10 | /// 11 | public static partial class ReadOnlyDbSetExtensions 12 | { 13 | /// 14 | /// Adds an item to the end of the mocked readonly db set source. 15 | /// 16 | /// The entity type. 17 | /// The mocked readonly db set. 18 | /// The item to be added to the end of the mocked readonly db set source. 19 | public static void AddToReadOnlySource(this DbSet mockedReadOnlyDbSet, TEntity item) where TEntity : class 20 | { 21 | EnsureArgument.IsNotNull(mockedReadOnlyDbSet, nameof(mockedReadOnlyDbSet)); 22 | EnsureArgument.IsNotNull(item, nameof(item)); 23 | 24 | var list = mockedReadOnlyDbSet.ToList(); 25 | list.Add(item); 26 | 27 | mockedReadOnlyDbSet.SetSource(list); 28 | } 29 | 30 | /// 31 | /// Adds the items of the specified sequence to the end of the mocked readonly db set source. 32 | /// 33 | /// The entity type. 34 | /// The mocked readonly db set. 35 | /// The sequence whose items should be added to the end of the mocked readonly db set source. 36 | public static void AddRangeToReadOnlySource(this DbSet mockedReadOnlyDbSet, IEnumerable items) where TEntity : class 37 | { 38 | EnsureArgument.IsNotNull(mockedReadOnlyDbSet, nameof(mockedReadOnlyDbSet)); 39 | EnsureArgument.IsNotEmpty(items, nameof(items)); 40 | 41 | var list = mockedReadOnlyDbSet.ToList(); 42 | list.AddRange(items); 43 | 44 | mockedReadOnlyDbSet.SetSource(list); 45 | } 46 | 47 | /// 48 | /// Removes all items from the mocked readonly db set source. 49 | /// 50 | /// The entity type. 51 | /// The mocked readonly db set. 52 | public static void ClearReadOnlySource(this DbSet mockedReadOnlyDbSet) where TEntity : class 53 | { 54 | EnsureArgument.IsNotNull(mockedReadOnlyDbSet, nameof(mockedReadOnlyDbSet)); 55 | mockedReadOnlyDbSet.SetSource(new List()); 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /EntityFrameworkCore.Testing.Moq.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | EntityFrameworkCore.Testing.Moq 5 | 10.0.0 6 | rgvlee 7 | rgvlee 8 | false 9 | LICENSE 10 | https://github.com/rgvlee/EntityFrameworkCore.Testing 11 | Adds relational support to the Microsoft EntityFrameworkCore in-memory database provider by mocking relational operations. 12 | 13 | EntityFrameworkCore.Testing v1.x = EntityFrameworkCore 2 (2.1.0+) 14 | EntityFrameworkCore.Testing v2.x = EntityFrameworkCore 3 15 | EntityFrameworkCore.Testing v3.x = EntityFrameworkCore 5 16 | EntityFrameworkCore.Testing v4.x = EntityFrameworkCore 6 17 | EntityFrameworkCore.Testing v5.x = EntityFrameworkCore 7 18 | EntityFrameworkCore.Testing v8.x = EntityFrameworkCore 8 19 | EntityFrameworkCore.Testing v9.x = EntityFrameworkCore 9 20 | EntityFrameworkCore.Testing v10.x = EntityFrameworkCore 10 21 | Copyright (c) 2025 Lee Anderson 22 | EntityFrameworkCore EFCore Moq mock testing 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /EntityFrameworkCore.Testing.NSubstitute.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | EntityFrameworkCore.Testing.NSubstitute 5 | 10.0.0 6 | rgvlee 7 | rgvlee 8 | false 9 | LICENSE 10 | https://github.com/rgvlee/EntityFrameworkCore.Testing 11 | Adds relational support to the Microsoft EntityFrameworkCore in-memory database provider by mocking relational operations. 12 | 13 | EntityFrameworkCore.Testing v1.x = EntityFrameworkCore 2 (2.1.0+) 14 | EntityFrameworkCore.Testing v2.x = EntityFrameworkCore 3 15 | EntityFrameworkCore.Testing v3.x = EntityFrameworkCore 5 16 | EntityFrameworkCore.Testing v4.x = EntityFrameworkCore 6 17 | EntityFrameworkCore.Testing v5.x = EntityFrameworkCore 7 18 | EntityFrameworkCore.Testing v8.x = EntityFrameworkCore 8 19 | EntityFrameworkCore.Testing v9.x = EntityFrameworkCore 9 20 | EntityFrameworkCore.Testing v10.x = EntityFrameworkCore 10 21 | Copyright (c) 2025 Lee Anderson 22 | EntityFrameworkCore EFCore NSubstitute nsub mock testing 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /src/EntityFrameworkCore.DefaultBehaviour.Tests/ByTypeDbSetTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using AutoFixture; 6 | using EntityFrameworkCore.Testing.Common.Tests; 7 | using FluentAssertions; 8 | using Microsoft.EntityFrameworkCore; 9 | using NUnit.Framework; 10 | using static FluentAssertions.FluentActions; 11 | 12 | namespace EntityFrameworkCore.DefaultBehaviour.Tests; 13 | 14 | public class ByTypeDbSetTests : BaseForQueryableTests 15 | { 16 | protected TestDbContext DbContext; 17 | 18 | protected DbSet DbSet => DbContext.Set(); 19 | 20 | protected override IQueryable Queryable => DbSet; 21 | 22 | [SetUp] 23 | public override void SetUp() 24 | { 25 | base.SetUp(); 26 | 27 | DbContext = new TestDbContext(new DbContextOptionsBuilder().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options); 28 | } 29 | 30 | protected override void SeedQueryableSource() 31 | { 32 | var itemsToAdd = Fixture.Build().With(p => p.CreatedAt, DateTime.Today).With(p => p.LastModifiedAt, DateTime.Today).CreateMany().ToList(); 33 | DbContext.Set().AddRange(itemsToAdd); 34 | DbContext.SaveChanges(); 35 | ItemsAddedToQueryableSource = itemsToAdd; 36 | } 37 | 38 | [Test] 39 | public virtual async Task AsAsyncEnumerable_ReturnsAsyncEnumerable() 40 | { 41 | var expectedResult = Fixture.Create(); 42 | DbSet.Add(expectedResult); 43 | DbContext.SaveChanges(); 44 | 45 | var asyncEnumerable = DbSet.AsAsyncEnumerable(); 46 | 47 | var actualResults = new List(); 48 | await foreach (var item in asyncEnumerable) actualResults.Add(item); 49 | 50 | Assert.Multiple(() => 51 | { 52 | Assert.That(actualResults.Single(), Is.EqualTo(expectedResult)); 53 | Assert.That(actualResults.Single(), Is.EqualTo(expectedResult)); 54 | }); 55 | } 56 | 57 | [Test] 58 | public virtual void AsQueryable_ReturnsQueryable() 59 | { 60 | var expectedResult = Fixture.Create(); 61 | DbSet.Add(expectedResult); 62 | DbContext.SaveChanges(); 63 | 64 | var queryable = DbSet.AsQueryable(); 65 | 66 | Assert.Multiple(() => 67 | { 68 | Assert.That(queryable.Single(), Is.EqualTo(expectedResult)); 69 | Assert.That(queryable.Single(), Is.EqualTo(expectedResult)); 70 | }); 71 | } 72 | 73 | [Test] 74 | public virtual void FromSqlInterpolated_ThrowsException() 75 | { 76 | Invoking(() => DbSet.FromSqlInterpolated($"sp_NoParams").ToList()).Should().ThrowExactly(); 77 | } 78 | 79 | [Test] 80 | public virtual void FromSqlRaw_ThrowsException() 81 | { 82 | Invoking(() => DbSet.FromSqlRaw("sp_NoParams").ToList()).Should().ThrowExactly(); 83 | } 84 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Common/Helpers/BaseMockedDbContextFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.Extensions.Logging; 6 | using rgvlee.Core.Common.Extensions; 7 | using rgvlee.Core.Common.Helpers; 8 | 9 | namespace EntityFrameworkCore.Testing.Common.Helpers 10 | { 11 | /// 12 | /// The base mocked db context factory. 13 | /// 14 | /// The db context type. 15 | public abstract class BaseMockedDbContextFactory where TDbContext : DbContext 16 | { 17 | /// 18 | /// The logger instance. 19 | /// 20 | protected static readonly ILogger Logger = LoggingHelper.CreateLogger>(); 21 | 22 | /// 23 | /// The parameters that will be used to create the mocked db context and, if one is not provided, 24 | /// the in-memory context that the mocked db context will use for in-memory provider supported operations. 25 | /// 26 | protected readonly List ConstructorParameters; 27 | 28 | /// 29 | /// The db context instance that the mocked db context will use for in-memory provider supported operations. 30 | /// 31 | protected readonly TDbContext DbContext; 32 | 33 | /// 34 | /// Constructor. 35 | /// 36 | /// The mocked db context factory options. 37 | protected BaseMockedDbContextFactory(MockedDbContextFactoryOptions options) 38 | { 39 | DbContext = options.DbContext; 40 | 41 | ConstructorParameters = options.ConstructorParameters?.ToList(); 42 | 43 | if (ConstructorParameters == null || !ConstructorParameters.Any()) 44 | { 45 | var dbContextType = typeof(TDbContext); 46 | 47 | if (!dbContextType.HasConstructor(typeof(DbContextOptions)) && 48 | !dbContextType.HasConstructor(typeof(DbContextOptions)) && 49 | !dbContextType.HasParameterlessConstructor()) 50 | { 51 | throw new MissingMethodException(ExceptionMessages.UnableToFindSuitableDbContextConstructor); 52 | } 53 | 54 | if (DbContext != null && dbContextType.HasParameterlessConstructor()) 55 | { 56 | ConstructorParameters = new List(); 57 | } 58 | else if (!dbContextType.HasConstructor(typeof(DbContextOptions<>))) 59 | { 60 | ConstructorParameters = new List { new DbContextOptionsBuilder().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options }; 61 | } 62 | else if (!dbContextType.HasConstructor(typeof(DbContextOptions))) 63 | { 64 | ConstructorParameters = new List { new DbContextOptionsBuilder().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options }; 65 | } 66 | } 67 | 68 | if (DbContext == null) 69 | { 70 | DbContext = (TDbContext) Activator.CreateInstance(typeof(TDbContext), ConstructorParameters?.ToArray()); 71 | } 72 | } 73 | 74 | /// 75 | /// Creates and sets up a mocked db context. 76 | /// 77 | /// A mocked db context. 78 | public abstract TDbContext Create(); 79 | } 80 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Common/ExceptionMessages.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace EntityFrameworkCore.Testing.Common { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | public class ExceptionMessages { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal ExceptionMessages() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | public static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("EntityFrameworkCore.Testing.Common.ExceptionMessages", typeof(ExceptionMessages).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | public static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized string similar to Cannot create a DbSet for '{0}' because this type is not included in the model for the context.. 65 | /// 66 | public static string CannotCreateDbSetTypeNotIncludedInModel { 67 | get { 68 | return ResourceManager.GetString("CannotCreateDbSetTypeNotIncludedInModel", resourceCulture); 69 | } 70 | } 71 | 72 | /// 73 | /// Looks up a localized string similar to Unable to find a suitable constructor. TDbContext must have a parameterless or DbContextOptions/DbContextOptions<TDbContext> constructor.. 74 | /// 75 | public static string UnableToFindSuitableDbContextConstructor { 76 | get { 77 | return ResourceManager.GetString("UnableToFindSuitableDbContextConstructor", resourceCulture); 78 | } 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Common/Helpers/ExpressionHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | using System.Reflection; 6 | using Microsoft.EntityFrameworkCore.Query.Internal; 7 | using Microsoft.Extensions.Logging; 8 | using rgvlee.Core.Common.Helpers; 9 | 10 | namespace EntityFrameworkCore.Testing.Common.Helpers 11 | { 12 | /// 13 | /// A helper for expressions. 14 | /// 15 | public static class ExpressionHelper 16 | { 17 | private static readonly ILogger Logger = LoggingHelper.CreateLogger(typeof(ExpressionHelper)); 18 | 19 | /// 20 | /// Creates a property expression for the specified property. 21 | /// 22 | /// The expression parameter. 23 | /// The expression property. 24 | /// The property info of the property to create the expression for. 25 | /// A property expression for the specified property. 26 | public static Expression> CreatePropertyExpression(PropertyInfo propertyInfo) 27 | { 28 | EnsureArgument.IsNotNull(propertyInfo, nameof(propertyInfo)); 29 | 30 | var parameter = Expression.Parameter(typeof(TParameter)); 31 | return Expression.Lambda>(Expression.Property(parameter, propertyInfo), parameter); 32 | } 33 | 34 | public static bool SqlAndParametersMatchFromSqlExpression(string sql, IEnumerable parameters, FromSqlQueryRootExpression expression) 35 | { 36 | EnsureArgument.IsNotNull(expression, nameof(expression)); 37 | EnsureArgument.IsNotNull(parameters, nameof(parameters)); 38 | 39 | var result = SqlMatchesFromSqlExpression(sql, expression) && 40 | ParameterMatchingHelper.DoInvocationParametersMatchSetUpParameters(parameters, (object[]) ((ConstantExpression) expression.Argument).Value); 41 | 42 | Logger.LogDebug("Match? {result}", result); 43 | 44 | return result; 45 | } 46 | 47 | private static bool SqlMatchesFromSqlExpression(string sql, FromSqlQueryRootExpression expression) 48 | { 49 | EnsureArgument.IsNotNull(expression, nameof(expression)); 50 | 51 | var expressionSql = expression.Sql; 52 | var parts = new List(); 53 | parts.Add($"Invocation sql: '{expressionSql}'"); 54 | parts.Add($"Set up sql: '{sql}'"); 55 | Logger.LogDebug(string.Join(Environment.NewLine, parts)); 56 | 57 | var result = expressionSql.Contains(sql, StringComparison.OrdinalIgnoreCase); 58 | 59 | Logger.LogDebug("Match? {result}", result); 60 | 61 | return result; 62 | } 63 | 64 | public static string StringifyFromSqlExpression(FromSqlQueryRootExpression expression) 65 | { 66 | EnsureArgument.IsNotNull(expression, nameof(expression)); 67 | 68 | var expressionSql = expression.Sql; 69 | var expressionParameters = (object[]) ((ConstantExpression) expression.Argument).Value; 70 | var parts = new List(); 71 | parts.Add($"Invocation sql: '{expressionSql}'"); 72 | parts.Add("Invocation Parameters:"); 73 | parts.Add(ParameterMatchingHelper.StringifyParameters(expressionParameters)); 74 | return string.Join(Environment.NewLine, parts); 75 | } 76 | 77 | public static void ThrowIfExpressionIsNotSupported(Expression expression) 78 | { 79 | if (expression is MethodCallExpression mce) 80 | { 81 | Logger.LogDebug("{methodName} invoked; expression: '{expression}'", mce.Method.Name, mce); 82 | 83 | if (mce.Method.Name.Equals(nameof(Queryable.ElementAt))) 84 | { 85 | throw new InvalidOperationException(); 86 | } 87 | 88 | if (mce.Method.Name.Equals(nameof(Queryable.ElementAtOrDefault))) 89 | { 90 | throw new InvalidOperationException(); 91 | } 92 | 93 | if (mce.Method.Name.Equals(nameof(Queryable.Select))) 94 | { 95 | var unaryExpression = (UnaryExpression) mce.Arguments[1]; 96 | var predicateExpression = unaryExpression.Operand; 97 | if (predicateExpression.Type.GetGenericArguments().ToList().Count.Equals(3)) 98 | { 99 | throw new InvalidOperationException(); 100 | } 101 | } 102 | 103 | if (mce.Method.Name.Equals(nameof(Queryable.SkipWhile))) 104 | { 105 | throw new InvalidOperationException(); 106 | } 107 | 108 | if (mce.Method.Name.Equals(nameof(Queryable.TakeWhile))) 109 | { 110 | throw new InvalidOperationException(); 111 | } 112 | } 113 | } 114 | } 115 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.NSubstitute/Extensions/DbSetExtensions.Internal.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.ComponentModel; 5 | using System.Linq; 6 | using System.Threading; 7 | using Microsoft.EntityFrameworkCore; 8 | using Microsoft.EntityFrameworkCore.Infrastructure; 9 | using NSubstitute; 10 | using rgvlee.Core.Common.Helpers; 11 | 12 | namespace EntityFrameworkCore.Testing.NSubstitute.Extensions 13 | { 14 | /// 15 | /// Extensions for db sets. 16 | /// 17 | public static class DbSetExtensions 18 | { 19 | internal static DbSet CreateMockedDbSet(this DbSet dbSet) where TEntity : class 20 | { 21 | EnsureArgument.IsNotNull(dbSet, nameof(dbSet)); 22 | 23 | var mockedDbSet = (DbSet) Substitute.For(new[] { 24 | typeof(DbSet), 25 | typeof(IAsyncEnumerable), 26 | typeof(IEnumerable), 27 | typeof(IEnumerable), 28 | typeof(IInfrastructure), 29 | typeof(IListSource), 30 | typeof(IQueryable) 31 | }, 32 | new object[] { }); 33 | 34 | var mockedQueryProvider = ((IQueryable) dbSet).Provider.CreateMockedQueryProvider(dbSet); 35 | 36 | mockedDbSet.Add(Arg.Any()).Returns(callInfo => dbSet.Add(callInfo.Arg())); 37 | mockedDbSet.AddAsync(Arg.Any(), Arg.Any()).Returns(callInfo => dbSet.AddAsync(callInfo.Arg(), callInfo.Arg())); 38 | mockedDbSet.When(x => x.AddRange(Arg.Any>())).Do(callInfo => dbSet.AddRange(callInfo.Arg>())); 39 | mockedDbSet.When(x => x.AddRange(Arg.Any())).Do(callInfo => dbSet.AddRange(callInfo.Arg())); 40 | mockedDbSet.AddRangeAsync(Arg.Any>(), Arg.Any()) 41 | .Returns(callInfo => dbSet.AddRangeAsync(callInfo.Arg>(), callInfo.Arg())); 42 | mockedDbSet.AddRangeAsync(Arg.Any()).Returns(callInfo => dbSet.AddRangeAsync(callInfo.Arg())); 43 | 44 | mockedDbSet.Attach(Arg.Any()).Returns(callInfo => dbSet.Attach(callInfo.Arg())); 45 | mockedDbSet.When(x => x.AttachRange(Arg.Any>())).Do(callInfo => dbSet.AttachRange(callInfo.Arg>())); 46 | mockedDbSet.When(x => x.AttachRange(Arg.Any())).Do(callInfo => dbSet.AttachRange(callInfo.Arg())); 47 | 48 | ((IListSource) mockedDbSet).ContainsListCollection.Returns(callInfo => ((IListSource) dbSet).ContainsListCollection); 49 | 50 | ((IQueryable) mockedDbSet).ElementType.Returns(callInfo => ((IQueryable) dbSet).ElementType); 51 | mockedDbSet.EntityType.Returns(callInfo => dbSet.EntityType); 52 | ((IQueryable) mockedDbSet).Expression.Returns(callInfo => ((IQueryable) dbSet).Expression); 53 | 54 | mockedDbSet.Find(Arg.Any()).Returns(callInfo => dbSet.Find(callInfo.Arg())); 55 | mockedDbSet.FindAsync(Arg.Any()).Returns(callInfo => dbSet.FindAsync(callInfo.Arg())); 56 | mockedDbSet.FindAsync(Arg.Any(), Arg.Any()) 57 | .Returns(callInfo => dbSet.FindAsync(callInfo.Arg(), callInfo.Arg())); 58 | 59 | ((IAsyncEnumerable) mockedDbSet).GetAsyncEnumerator(Arg.Any()) 60 | .Returns(callInfo => ((IAsyncEnumerable) dbSet).GetAsyncEnumerator(callInfo.Arg())); 61 | 62 | ((IEnumerable) mockedDbSet).GetEnumerator().Returns(callInfo => ((IEnumerable) dbSet).GetEnumerator()); 63 | ((IEnumerable) mockedDbSet).GetEnumerator().Returns(callInfo => ((IEnumerable) dbSet).GetEnumerator()); 64 | 65 | /* 66 | * System.NotSupportedException : Data binding directly to a store query is not supported. Instead populate a DbSet with data, 67 | * for example by calling Load on the DbSet, and then bind to local data to avoid sending a query to the database each time the 68 | * databound control iterates the data. For WPF bind to 'DbSet.Local.ToObservableCollection()'. For WinForms bind to 69 | * 'DbSet.Local.ToBindingList()'. For ASP.NET WebForms bind to 'DbSet.ToList()' or use Model Binding. 70 | */ 71 | ((IListSource) mockedDbSet).GetList().Returns(callInfo => dbSet.ToList()); 72 | 73 | ((IInfrastructure) mockedDbSet).Instance.Returns(callInfo => ((IInfrastructure) dbSet).Instance); 74 | 75 | mockedDbSet.Local.Returns(callInfo => dbSet.Local); 76 | 77 | mockedDbSet.Remove(Arg.Any()).Returns(callInfo => dbSet.Remove(callInfo.Arg())); 78 | mockedDbSet.When(x => x.RemoveRange(Arg.Any>())).Do(callInfo => dbSet.RemoveRange(callInfo.Arg>())); 79 | mockedDbSet.When(x => x.RemoveRange(Arg.Any())).Do(callInfo => dbSet.RemoveRange(callInfo.Arg())); 80 | 81 | mockedDbSet.Update(Arg.Any()).Returns(callInfo => dbSet.Update(callInfo.Arg())); 82 | mockedDbSet.When(x => x.UpdateRange(Arg.Any>())).Do(callInfo => dbSet.UpdateRange(callInfo.Arg>())); 83 | mockedDbSet.When(x => x.UpdateRange(Arg.Any())).Do(callInfo => dbSet.UpdateRange(callInfo.Arg())); 84 | 85 | ((IQueryable) mockedDbSet).Provider.Returns(callInfo => mockedQueryProvider); 86 | 87 | mockedDbSet.AsAsyncEnumerable().Returns(callInfo => dbSet.AsAsyncEnumerable()); 88 | mockedDbSet.AsQueryable().Returns(callInfo => dbSet); 89 | 90 | return mockedDbSet; 91 | } 92 | } 93 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Common/AsyncQueryProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | using System.Reflection; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | using Microsoft.EntityFrameworkCore.Query; 9 | using Microsoft.EntityFrameworkCore.Query.Internal; 10 | using Microsoft.Extensions.Logging; 11 | using rgvlee.Core.Common.Helpers; 12 | using ProjectExpressionHelper = EntityFrameworkCore.Testing.Common.Helpers.ExpressionHelper; 13 | 14 | namespace EntityFrameworkCore.Testing.Common 15 | { 16 | /// 17 | public class AsyncQueryProvider : IAsyncQueryProvider 18 | { 19 | private static readonly ILogger Logger = LoggingHelper.CreateLogger>(); 20 | 21 | public AsyncQueryProvider(IEnumerable enumerable) 22 | { 23 | Source = enumerable.AsQueryable(); 24 | } 25 | 26 | /// 27 | /// The query provider source. 28 | /// 29 | public IQueryable Source { get; set; } 30 | 31 | /// 32 | /// In this implementation it is just a wrapper for 33 | public virtual IQueryable CreateQuery(Expression expression) 34 | { 35 | Logger.LogDebug("CreateQuery: invoked"); 36 | 37 | //Handles cases where we are projecting to another type 38 | if (expression is MethodCallExpression mce) 39 | { 40 | var returnType = mce.Method.ReturnType; 41 | if (returnType.GetGenericTypeDefinition() != typeof(IQueryable<>)) 42 | { 43 | throw new InvalidOperationException($"Expected IQueryable<>; actual {returnType.FullName}"); 44 | } 45 | 46 | var createQueryMethod = typeof(IQueryProvider).GetMethods().Single(x => x.Name.Equals(nameof(IQueryProvider.CreateQuery)) && x.IsGenericMethod); 47 | 48 | var createQueryResult = createQueryMethod.MakeGenericMethod(returnType.GetGenericArguments().Single()).Invoke(this, new[] { expression }); 49 | 50 | return (IQueryable) Activator.CreateInstance(typeof(AsyncEnumerable<>).GetGenericTypeDefinition().MakeGenericType(returnType.GetGenericArguments().Single()), 51 | createQueryResult); 52 | } 53 | 54 | return CreateQuery(expression); 55 | } 56 | 57 | /// 58 | public virtual IQueryable CreateQuery(Expression expression) 59 | { 60 | Logger.LogDebug("CreateQuery: invoked"); 61 | 62 | if (expression is FromSqlQueryRootExpression) 63 | { 64 | Logger.LogDebug("CreateQuery: catch all exception invoked"); 65 | throw new NotSupportedException(); 66 | } 67 | 68 | ProjectExpressionHelper.ThrowIfExpressionIsNotSupported(expression); 69 | 70 | return new AsyncEnumerable(Source.Provider.CreateQuery(EnsureExpressionCanBeResolvedBySourceProvider(expression))); 71 | } 72 | 73 | /// 74 | public virtual object Execute(Expression expression) 75 | { 76 | Logger.LogDebug("Execute: invoked"); 77 | ProjectExpressionHelper.ThrowIfExpressionIsNotSupported(expression); 78 | return Source.Provider.Execute(EnsureExpressionCanBeResolvedBySourceProvider(expression)); 79 | } 80 | 81 | /// 82 | public virtual TResult Execute(Expression expression) 83 | { 84 | Logger.LogDebug("Execute: invoked"); 85 | ProjectExpressionHelper.ThrowIfExpressionIsNotSupported(expression); 86 | return Source.Provider.Execute(EnsureExpressionCanBeResolvedBySourceProvider(expression)); 87 | } 88 | 89 | /// 90 | public virtual TResult ExecuteAsync(Expression expression, CancellationToken cancellationToken) 91 | { 92 | //TResult is a Task. The provider requires T. 93 | return (TResult) typeof(AsyncQueryProvider).GetMethod(nameof(WrapExecuteAsync), BindingFlags.Instance | BindingFlags.NonPublic) 94 | .MakeGenericMethod(typeof(TResult).GetGenericArguments()) 95 | .Invoke(this, new object[] { expression, cancellationToken }); 96 | } 97 | 98 | private Task WrapExecuteAsync(Expression expression, CancellationToken cancellationToken) 99 | { 100 | return Task.FromResult(Execute(expression)); 101 | } 102 | 103 | private Expression EnsureExpressionCanBeResolvedBySourceProvider(Expression expression) 104 | { 105 | Logger.LogDebug("EnsureExpressionCanBeResolvedBySourceProvider: invoked"); 106 | 107 | if (expression is MethodCallExpression mce && mce.Arguments[0] is Microsoft.EntityFrameworkCore.Query.QueryRootExpression) 108 | { 109 | for (var i = 0; i < mce.Arguments.Count; i++) 110 | { 111 | Logger.LogDebug("argument[{i}]: {argument}", i, mce.Arguments[i].ToString()); 112 | } 113 | 114 | //This ensures that Source provider will always be able to resolve the expression 115 | var arguments = new List(); 116 | arguments.Add(Source.Expression); 117 | arguments.AddRange(mce.Arguments.Skip(1)); 118 | 119 | Logger.LogDebug("sourceExpression: {sourceExpression}", Source.Expression.ToString()); 120 | 121 | for (var i = 0; i < mce.Arguments.Count; i++) 122 | { 123 | Logger.LogDebug("argument[{i}]: {argument}", i, mce.Arguments[i].ToString()); 124 | } 125 | 126 | return Expression.Call(mce.Method, arguments); 127 | } 128 | 129 | return expression; 130 | } 131 | } 132 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Moq/Extensions/DbSetExtensions.Internal.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.ComponentModel; 5 | using System.Linq; 6 | using System.Threading; 7 | using Microsoft.EntityFrameworkCore; 8 | using Microsoft.EntityFrameworkCore.Infrastructure; 9 | using Moq; 10 | using rgvlee.Core.Common.Helpers; 11 | 12 | namespace EntityFrameworkCore.Testing.Moq.Extensions 13 | { 14 | /// 15 | /// Extensions for db sets. 16 | /// 17 | public static class DbSetExtensions 18 | { 19 | internal static DbSet CreateMockedDbSet(this DbSet dbSet) where TEntity : class 20 | { 21 | EnsureArgument.IsNotNull(dbSet, nameof(dbSet)); 22 | 23 | var dbSetMock = new Mock>(); 24 | 25 | var mockedQueryProvider = ((IQueryable) dbSet).Provider.CreateMockedQueryProvider(dbSet); 26 | 27 | dbSetMock.Setup(m => m.Add(It.IsAny())).Returns((TEntity providedEntity) => dbSet.Add(providedEntity)); 28 | dbSetMock.Setup(m => m.AddAsync(It.IsAny(), It.IsAny())) 29 | .Returns((TEntity providedEntity, CancellationToken providedCancellationToken) => dbSet.AddAsync(providedEntity, providedCancellationToken)); 30 | dbSetMock.Setup(m => m.AddRange(It.IsAny>())).Callback((IEnumerable providedEntities) => dbSet.AddRange(providedEntities)); 31 | dbSetMock.Setup(m => m.AddRange(It.IsAny())).Callback((TEntity[] providedEntities) => dbSet.AddRange(providedEntities)); 32 | dbSetMock.Setup(m => m.AddRangeAsync(It.IsAny>(), It.IsAny())) 33 | .Returns((IEnumerable providedEntities, CancellationToken providedCancellationToken) => dbSet.AddRangeAsync(providedEntities, providedCancellationToken)); 34 | dbSetMock.Setup(m => m.AddRangeAsync(It.IsAny())).Returns((TEntity[] providedEntities) => dbSet.AddRangeAsync(providedEntities)); 35 | 36 | dbSetMock.Setup(m => m.Attach(It.IsAny())).Returns((TEntity providedEntity) => dbSet.Attach(providedEntity)); 37 | dbSetMock.Setup(m => m.AttachRange(It.IsAny>())).Callback((IEnumerable providedEntities) => dbSet.AttachRange(providedEntities)); 38 | dbSetMock.Setup(m => m.AttachRange(It.IsAny())).Callback((TEntity[] providedEntities) => dbSet.AttachRange(providedEntities)); 39 | 40 | dbSetMock.As().Setup(m => m.ContainsListCollection).Returns(() => ((IListSource) dbSet).ContainsListCollection); 41 | 42 | dbSetMock.As>().Setup(m => m.ElementType).Returns(() => ((IQueryable) dbSet).ElementType); 43 | dbSetMock.Setup(m => m.EntityType).Returns(() => dbSet.EntityType); 44 | dbSetMock.As>().Setup(m => m.Expression).Returns(() => ((IQueryable) dbSet).Expression); 45 | 46 | dbSetMock.Setup(m => m.Find(It.IsAny())).Returns((object[] providedKeyValues) => dbSet.Find(providedKeyValues)); 47 | dbSetMock.Setup(m => m.FindAsync(It.IsAny())).Returns((object[] providedKeyValues) => dbSet.FindAsync(providedKeyValues)); 48 | dbSetMock.Setup(m => m.FindAsync(It.IsAny(), It.IsAny())) 49 | .Returns((object[] providedKeyValues, CancellationToken providedCancellationToken) => dbSet.FindAsync(providedKeyValues, providedCancellationToken)); 50 | 51 | dbSetMock.As>() 52 | .Setup(m => m.GetAsyncEnumerator(It.IsAny())) 53 | .Returns((CancellationToken providedCancellationToken) => ((IAsyncEnumerable) dbSet).GetAsyncEnumerator(providedCancellationToken)); 54 | 55 | dbSetMock.As().Setup(m => m.GetEnumerator()).Returns(() => ((IEnumerable) dbSet).GetEnumerator()); 56 | dbSetMock.As>().Setup(m => m.GetEnumerator()).Returns(() => ((IEnumerable) dbSet).GetEnumerator()); 57 | 58 | /* 59 | * System.NotSupportedException : Data binding directly to a store query is not supported. Instead populate a DbSet with data, 60 | * for example by calling Load on the DbSet, and then bind to local data to avoid sending a query to the database each time the 61 | * databound control iterates the data. For WPF bind to 'DbSet.Local.ToObservableCollection()'. For WinForms bind to 62 | * 'DbSet.Local.ToBindingList()'. For ASP.NET WebForms bind to 'DbSet.ToList()' or use Model Binding. 63 | */ 64 | dbSetMock.As().Setup(m => m.GetList()).Returns(() => dbSet.ToList()); 65 | 66 | dbSetMock.As>().Setup(m => m.Instance).Returns(() => ((IInfrastructure) dbSet).Instance); 67 | 68 | dbSetMock.Setup(m => m.Local).Returns(() => dbSet.Local); 69 | 70 | dbSetMock.Setup(m => m.Remove(It.IsAny())).Returns((TEntity providedEntity) => dbSet.Remove(providedEntity)); 71 | dbSetMock.Setup(m => m.RemoveRange(It.IsAny>())).Callback((IEnumerable providedEntities) => dbSet.RemoveRange(providedEntities)); 72 | dbSetMock.Setup(m => m.RemoveRange(It.IsAny())).Callback((TEntity[] providedEntities) => dbSet.RemoveRange(providedEntities)); 73 | 74 | dbSetMock.Setup(m => m.Update(It.IsAny())).Returns((TEntity providedEntity) => dbSet.Update(providedEntity)); 75 | dbSetMock.Setup(m => m.UpdateRange(It.IsAny>())).Callback((IEnumerable providedEntities) => dbSet.UpdateRange(providedEntities)); 76 | dbSetMock.Setup(m => m.UpdateRange(It.IsAny())).Callback((TEntity[] providedEntities) => dbSet.UpdateRange(providedEntities)); 77 | 78 | dbSetMock.As>().Setup(m => m.Provider).Returns(() => mockedQueryProvider); 79 | 80 | dbSetMock.Setup(m => m.AsAsyncEnumerable()).Returns(() => dbSet.AsAsyncEnumerable()); 81 | dbSetMock.Setup(m => m.AsQueryable()).Returns(() => dbSet); 82 | 83 | return dbSetMock.Object; 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /EntityFrameworkCore.Testing.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.3.32811.315 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F7DF11CE-7549-4808-B9BE-66CE1BD1F150}" 7 | ProjectSection(SolutionItems) = preProject 8 | .gitignore = .gitignore 9 | .github\workflows\continuous-integration-checks.yml = .github\workflows\continuous-integration-checks.yml 10 | src\EntityFrameworkCore.Testing.Common\EntityFrameworkCore.Testing.Common.xml = src\EntityFrameworkCore.Testing.Common\EntityFrameworkCore.Testing.Common.xml 11 | EntityFrameworkCore.Testing.Moq.nuspec = EntityFrameworkCore.Testing.Moq.nuspec 12 | src\EntityFrameworkCore.Testing.Moq\EntityFrameworkCore.Testing.Moq.xml = src\EntityFrameworkCore.Testing.Moq\EntityFrameworkCore.Testing.Moq.xml 13 | EntityFrameworkCore.Testing.NSubstitute.nuspec = EntityFrameworkCore.Testing.NSubstitute.nuspec 14 | src\EntityFrameworkCore.Testing.NSubstitute\EntityFrameworkCore.Testing.NSubstitute.xml = src\EntityFrameworkCore.Testing.NSubstitute\EntityFrameworkCore.Testing.NSubstitute.xml 15 | googlea6bd68d4a55b1e59.html = googlea6bd68d4a55b1e59.html 16 | LICENSE = LICENSE 17 | README.md = README.md 18 | .github\workflows\release.yml = .github\workflows\release.yml 19 | TODO.md = TODO.md 20 | EndProjectSection 21 | EndProject 22 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EntityFrameworkCore.Testing.Moq", "src\EntityFrameworkCore.Testing.Moq\EntityFrameworkCore.Testing.Moq.csproj", "{3A00A558-6614-4D2C-8BC0-A74EFBB8F844}" 23 | EndProject 24 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EntityFrameworkCore.Testing.Moq.Tests", "src\EntityFrameworkCore.Testing.Moq.Tests\EntityFrameworkCore.Testing.Moq.Tests.csproj", "{6567AA47-8E4D-4E69-8075-B8C25DC7F4A4}" 25 | EndProject 26 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{5B717CD0-96CD-4862-95EB-80ECCDCD1D07}" 27 | EndProject 28 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EntityFrameworkCore.Testing.Common", "src\EntityFrameworkCore.Testing.Common\EntityFrameworkCore.Testing.Common.csproj", "{F2211544-E6EA-439A-9C31-3972B48B9D5E}" 29 | EndProject 30 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EntityFrameworkCore.Testing.Common.Tests", "src\EntityFrameworkCore.Testing.Common.Tests\EntityFrameworkCore.Testing.Common.Tests.csproj", "{4B97C16B-E27D-4900-A535-6D5AC116B893}" 31 | EndProject 32 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EntityFrameworkCore.DefaultBehaviour.Tests", "src\EntityFrameworkCore.DefaultBehaviour.Tests\EntityFrameworkCore.DefaultBehaviour.Tests.csproj", "{9C08E46C-C902-473F-93E6-FCB89DEC8C97}" 33 | EndProject 34 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EntityFrameworkCore.Testing.NSubstitute", "src\EntityFrameworkCore.Testing.NSubstitute\EntityFrameworkCore.Testing.NSubstitute.csproj", "{A70976F0-38EA-461C-9BDE-BEE8232B048D}" 35 | EndProject 36 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EntityFrameworkCore.Testing.NSubstitute.Tests", "src\EntityFrameworkCore.Testing.NSubstitute.Tests\EntityFrameworkCore.Testing.NSubstitute.Tests.csproj", "{2F67273D-B7B8-49A5-9A91-E37CBC10F563}" 37 | EndProject 38 | Global 39 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 40 | Debug|Any CPU = Debug|Any CPU 41 | Release|Any CPU = Release|Any CPU 42 | EndGlobalSection 43 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 44 | {3A00A558-6614-4D2C-8BC0-A74EFBB8F844}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 45 | {3A00A558-6614-4D2C-8BC0-A74EFBB8F844}.Debug|Any CPU.Build.0 = Debug|Any CPU 46 | {3A00A558-6614-4D2C-8BC0-A74EFBB8F844}.Release|Any CPU.ActiveCfg = Release|Any CPU 47 | {3A00A558-6614-4D2C-8BC0-A74EFBB8F844}.Release|Any CPU.Build.0 = Release|Any CPU 48 | {6567AA47-8E4D-4E69-8075-B8C25DC7F4A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 49 | {6567AA47-8E4D-4E69-8075-B8C25DC7F4A4}.Debug|Any CPU.Build.0 = Debug|Any CPU 50 | {6567AA47-8E4D-4E69-8075-B8C25DC7F4A4}.Release|Any CPU.ActiveCfg = Release|Any CPU 51 | {6567AA47-8E4D-4E69-8075-B8C25DC7F4A4}.Release|Any CPU.Build.0 = Release|Any CPU 52 | {F2211544-E6EA-439A-9C31-3972B48B9D5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 53 | {F2211544-E6EA-439A-9C31-3972B48B9D5E}.Debug|Any CPU.Build.0 = Debug|Any CPU 54 | {F2211544-E6EA-439A-9C31-3972B48B9D5E}.Release|Any CPU.ActiveCfg = Release|Any CPU 55 | {F2211544-E6EA-439A-9C31-3972B48B9D5E}.Release|Any CPU.Build.0 = Release|Any CPU 56 | {4B97C16B-E27D-4900-A535-6D5AC116B893}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 57 | {4B97C16B-E27D-4900-A535-6D5AC116B893}.Debug|Any CPU.Build.0 = Debug|Any CPU 58 | {4B97C16B-E27D-4900-A535-6D5AC116B893}.Release|Any CPU.ActiveCfg = Release|Any CPU 59 | {4B97C16B-E27D-4900-A535-6D5AC116B893}.Release|Any CPU.Build.0 = Release|Any CPU 60 | {9C08E46C-C902-473F-93E6-FCB89DEC8C97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 61 | {9C08E46C-C902-473F-93E6-FCB89DEC8C97}.Debug|Any CPU.Build.0 = Debug|Any CPU 62 | {9C08E46C-C902-473F-93E6-FCB89DEC8C97}.Release|Any CPU.ActiveCfg = Release|Any CPU 63 | {9C08E46C-C902-473F-93E6-FCB89DEC8C97}.Release|Any CPU.Build.0 = Release|Any CPU 64 | {A70976F0-38EA-461C-9BDE-BEE8232B048D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 65 | {A70976F0-38EA-461C-9BDE-BEE8232B048D}.Debug|Any CPU.Build.0 = Debug|Any CPU 66 | {A70976F0-38EA-461C-9BDE-BEE8232B048D}.Release|Any CPU.ActiveCfg = Release|Any CPU 67 | {A70976F0-38EA-461C-9BDE-BEE8232B048D}.Release|Any CPU.Build.0 = Release|Any CPU 68 | {2F67273D-B7B8-49A5-9A91-E37CBC10F563}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 69 | {2F67273D-B7B8-49A5-9A91-E37CBC10F563}.Debug|Any CPU.Build.0 = Debug|Any CPU 70 | {2F67273D-B7B8-49A5-9A91-E37CBC10F563}.Release|Any CPU.ActiveCfg = Release|Any CPU 71 | {2F67273D-B7B8-49A5-9A91-E37CBC10F563}.Release|Any CPU.Build.0 = Release|Any CPU 72 | EndGlobalSection 73 | GlobalSection(SolutionProperties) = preSolution 74 | HideSolutionNode = FALSE 75 | EndGlobalSection 76 | GlobalSection(NestedProjects) = preSolution 77 | {6567AA47-8E4D-4E69-8075-B8C25DC7F4A4} = {5B717CD0-96CD-4862-95EB-80ECCDCD1D07} 78 | {4B97C16B-E27D-4900-A535-6D5AC116B893} = {5B717CD0-96CD-4862-95EB-80ECCDCD1D07} 79 | {9C08E46C-C902-473F-93E6-FCB89DEC8C97} = {5B717CD0-96CD-4862-95EB-80ECCDCD1D07} 80 | {2F67273D-B7B8-49A5-9A91-E37CBC10F563} = {5B717CD0-96CD-4862-95EB-80ECCDCD1D07} 81 | EndGlobalSection 82 | GlobalSection(ExtensibilityGlobals) = postSolution 83 | SolutionGuid = {0E585345-42EF-438B-8212-2C328D36D9AD} 84 | EndGlobalSection 85 | EndGlobal 86 | -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Moq/Extensions/QueryableExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using rgvlee.Core.Common.Helpers; 5 | 6 | namespace EntityFrameworkCore.Testing.Moq.Extensions 7 | { 8 | /// 9 | /// Extensions for queryable collections. 10 | /// 11 | public static class QueryableExtensions 12 | { 13 | /// 14 | /// Sets up FromSqlInterpolated invocations to return a specified result. 15 | /// 16 | /// The queryable source type. 17 | /// The mocked queryable. 18 | /// The FromSqlInterpolated result. 19 | /// The mocked queryable. 20 | public static IQueryable AddFromSqlInterpolatedResult(this IQueryable mockedQueryable, IEnumerable fromSqlInterpolatedResult) where T : class 21 | { 22 | EnsureArgument.IsNotNull(mockedQueryable, nameof(mockedQueryable)); 23 | mockedQueryable.Provider.AddFromSqlRawResult(string.Empty, new List(), fromSqlInterpolatedResult); 24 | return mockedQueryable; 25 | } 26 | 27 | /// 28 | /// Sets up FromSqlInterpolated invocations to return a specified result. 29 | /// 30 | /// The queryable source type. 31 | /// The mocked queryable. 32 | /// The FromSqlInterpolated sql string. Set up supports case insensitive partial matches. 33 | /// The FromSqlInterpolated result. 34 | /// The mocked queryable. 35 | public static IQueryable AddFromSqlInterpolatedResult(this IQueryable mockedQueryable, FormattableString sql, IEnumerable fromSqlInterpolatedResult) 36 | where T : class 37 | { 38 | EnsureArgument.IsNotNull(mockedQueryable, nameof(mockedQueryable)); 39 | mockedQueryable.Provider.AddFromSqlRawResult(sql.Format, sql.GetArguments(), fromSqlInterpolatedResult); 40 | return mockedQueryable; 41 | } 42 | 43 | /// 44 | /// Sets up FromSqlInterpolated invocations to return a specified result. 45 | /// 46 | /// The queryable source type. 47 | /// The mocked queryable. 48 | /// The FromSqlInterpolated sql string. Set up supports case insensitive partial matches. 49 | /// The FromSqlInterpolated parameters. Set up supports case insensitive partial parameter sequence matching. 50 | /// The FromSqlInterpolated result. 51 | /// The mocked queryable. 52 | public static IQueryable AddFromSqlInterpolatedResult( 53 | this IQueryable mockedQueryable, string sql, IEnumerable parameters, IEnumerable fromSqlInterpolatedResult) where T : class 54 | { 55 | EnsureArgument.IsNotNull(mockedQueryable, nameof(mockedQueryable)); 56 | mockedQueryable.Provider.AddFromSqlRawResult(sql, parameters, fromSqlInterpolatedResult); 57 | return mockedQueryable; 58 | } 59 | 60 | /// 61 | /// Sets up FromSqlRaw invocations to return a specified result. 62 | /// 63 | /// The queryable source type. 64 | /// The mocked queryable. 65 | /// The FromSqlRaw result. 66 | /// The mocked queryable. 67 | public static IQueryable AddFromSqlRawResult(this IQueryable mockedQueryable, IEnumerable fromSqlRawResult) where T : class 68 | { 69 | EnsureArgument.IsNotNull(mockedQueryable, nameof(mockedQueryable)); 70 | mockedQueryable.Provider.AddFromSqlRawResult(string.Empty, new List(), fromSqlRawResult); 71 | return mockedQueryable; 72 | } 73 | 74 | /// 75 | /// Sets up FromSqlRaw invocations containing a specified sql string to return a specified result. 76 | /// 77 | /// The queryable source type. 78 | /// The mocked queryable. 79 | /// The FromSqlRaw sql string. Set up supports case insensitive partial matches. 80 | /// The FromSqlRaw result. 81 | /// The mocked queryable. 82 | public static IQueryable AddFromSqlRawResult(this IQueryable mockedQueryable, string sql, IEnumerable fromSqlRawResult) where T : class 83 | { 84 | EnsureArgument.IsNotNull(mockedQueryable, nameof(mockedQueryable)); 85 | mockedQueryable.Provider.AddFromSqlRawResult(sql, new List(), fromSqlRawResult); 86 | return mockedQueryable; 87 | } 88 | 89 | /// 90 | /// Sets up FromSqlRaw invocations containing a specified sql string and parameters to return a specified result. 91 | /// 92 | /// The queryable source type. 93 | /// The mocked queryable. 94 | /// The FromSqlRaw sql string. Set up supports case insensitive partial matches. 95 | /// The FromSqlRaw parameters. Set up supports case insensitive partial parameter sequence matching. 96 | /// The FromSqlRaw result. 97 | /// The mocked queryable. 98 | public static IQueryable AddFromSqlRawResult(this IQueryable mockedQueryable, string sql, IEnumerable parameters, IEnumerable fromSqlRawResult) 99 | where T : class 100 | { 101 | EnsureArgument.IsNotNull(mockedQueryable, nameof(mockedQueryable)); 102 | mockedQueryable.Provider.AddFromSqlRawResult(sql, parameters, fromSqlRawResult); 103 | return mockedQueryable; 104 | } 105 | } 106 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.NSubstitute/Extensions/QueryableExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using rgvlee.Core.Common.Helpers; 5 | 6 | namespace EntityFrameworkCore.Testing.NSubstitute.Extensions 7 | { 8 | /// 9 | /// Extensions for queryable collections. 10 | /// 11 | public static class QueryableExtensions 12 | { 13 | /// 14 | /// Sets up FromSqlInterpolated invocations to return a specified result. 15 | /// 16 | /// The queryable source type. 17 | /// The mocked queryable. 18 | /// The FromSqlInterpolated result. 19 | /// The mocked queryable. 20 | public static IQueryable AddFromSqlInterpolatedResult(this IQueryable mockedQueryable, IEnumerable fromSqlInterpolatedResult) where T : class 21 | { 22 | EnsureArgument.IsNotNull(mockedQueryable, nameof(mockedQueryable)); 23 | mockedQueryable.Provider.AddFromSqlRawResult(string.Empty, new List(), fromSqlInterpolatedResult); 24 | return mockedQueryable; 25 | } 26 | 27 | /// 28 | /// Sets up FromSqlInterpolated invocations to return a specified result. 29 | /// 30 | /// The queryable source type. 31 | /// The mocked queryable. 32 | /// The FromSqlInterpolated sql string. Set up supports case insensitive partial matches. 33 | /// The FromSqlInterpolated result. 34 | /// The mocked queryable. 35 | public static IQueryable AddFromSqlInterpolatedResult(this IQueryable mockedQueryable, FormattableString sql, IEnumerable fromSqlInterpolatedResult) 36 | where T : class 37 | { 38 | EnsureArgument.IsNotNull(mockedQueryable, nameof(mockedQueryable)); 39 | mockedQueryable.Provider.AddFromSqlRawResult(sql.Format, sql.GetArguments(), fromSqlInterpolatedResult); 40 | return mockedQueryable; 41 | } 42 | 43 | /// 44 | /// Sets up FromSqlInterpolated invocations to return a specified result. 45 | /// 46 | /// The queryable source type. 47 | /// The mocked queryable. 48 | /// The FromSqlInterpolated sql string. Set up supports case insensitive partial matches. 49 | /// The FromSqlInterpolated parameters. Set up supports case insensitive partial parameter sequence matching. 50 | /// The FromSqlInterpolated result. 51 | /// The mocked queryable. 52 | public static IQueryable AddFromSqlInterpolatedResult( 53 | this IQueryable mockedQueryable, string sql, IEnumerable parameters, IEnumerable fromSqlInterpolatedResult) where T : class 54 | { 55 | EnsureArgument.IsNotNull(mockedQueryable, nameof(mockedQueryable)); 56 | mockedQueryable.Provider.AddFromSqlRawResult(sql, parameters, fromSqlInterpolatedResult); 57 | return mockedQueryable; 58 | } 59 | 60 | /// 61 | /// Sets up FromSqlRaw invocations to return a specified result. 62 | /// 63 | /// The queryable source type. 64 | /// The mocked queryable. 65 | /// The FromSqlRaw result. 66 | /// The mocked queryable. 67 | public static IQueryable AddFromSqlRawResult(this IQueryable mockedQueryable, IEnumerable fromSqlRawResult) where T : class 68 | { 69 | EnsureArgument.IsNotNull(mockedQueryable, nameof(mockedQueryable)); 70 | mockedQueryable.Provider.AddFromSqlRawResult(string.Empty, new List(), fromSqlRawResult); 71 | return mockedQueryable; 72 | } 73 | 74 | /// 75 | /// Sets up FromSqlRaw invocations containing a specified sql string to return a specified result. 76 | /// 77 | /// The queryable source type. 78 | /// The mocked queryable. 79 | /// The FromSqlRaw sql string. Set up supports case insensitive partial matches. 80 | /// The FromSqlRaw result. 81 | /// The mocked queryable. 82 | public static IQueryable AddFromSqlRawResult(this IQueryable mockedQueryable, string sql, IEnumerable fromSqlRawResult) where T : class 83 | { 84 | EnsureArgument.IsNotNull(mockedQueryable, nameof(mockedQueryable)); 85 | mockedQueryable.Provider.AddFromSqlRawResult(sql, new List(), fromSqlRawResult); 86 | return mockedQueryable; 87 | } 88 | 89 | /// 90 | /// Sets up FromSqlRaw invocations containing a specified sql string and parameters to return a specified result. 91 | /// 92 | /// The queryable source type. 93 | /// The mocked queryable. 94 | /// The FromSqlRaw sql string. Set up supports case insensitive partial matches. 95 | /// The FromSqlRaw parameters. Set up supports case insensitive partial parameter sequence matching. 96 | /// The FromSqlRaw result. 97 | /// The mocked queryable. 98 | public static IQueryable AddFromSqlRawResult(this IQueryable mockedQueryable, string sql, IEnumerable parameters, IEnumerable fromSqlRawResult) 99 | where T : class 100 | { 101 | EnsureArgument.IsNotNull(mockedQueryable, nameof(mockedQueryable)); 102 | mockedQueryable.Provider.AddFromSqlRawResult(sql, parameters, fromSqlRawResult); 103 | return mockedQueryable; 104 | } 105 | } 106 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Common/ExceptionMessages.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | Cannot create a DbSet for '{0}' because this type is not included in the model for the context. 122 | 123 | 124 | Unable to find a suitable constructor. TDbContext must have a parameterless or DbContextOptions/DbContextOptions<TDbContext> constructor. 125 | 126 | -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Common.Tests/BaseForDbSetTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using AutoFixture; 6 | using Microsoft.EntityFrameworkCore; 7 | using NUnit.Framework; 8 | 9 | namespace EntityFrameworkCore.Testing.Common.Tests 10 | { 11 | public abstract class BaseForDbSetTests : BaseForMockedQueryableTests where TDbContext : DbContext 12 | where TEntity : BaseTestEntity 13 | { 14 | protected TDbContext MockedDbContext; 15 | 16 | [SetUp] 17 | public override void SetUp() 18 | { 19 | base.SetUp(); 20 | 21 | MockedDbContext = CreateMockedDbContext(); 22 | } 23 | 24 | [TearDown] 25 | public override void TearDown() 26 | { 27 | MockedDbContext.Dispose(); 28 | 29 | base.TearDown(); 30 | } 31 | 32 | protected override void SeedQueryableSource() 33 | { 34 | var itemsToAdd = Fixture.Build().With(p => p.CreatedAt, DateTime.Today).With(p => p.LastModifiedAt, DateTime.Today).CreateMany().ToList(); 35 | DbSet.AddRange(itemsToAdd); 36 | MockedDbContext.SaveChanges(); 37 | ItemsAddedToQueryableSource = itemsToAdd; 38 | } 39 | 40 | protected abstract TDbContext CreateMockedDbContext(); 41 | 42 | [Test] 43 | public virtual void AddAndPersist_Item_AddsAndPersistsItem() 44 | { 45 | var expectedResult = Fixture.Create(); 46 | 47 | DbSet.Add(expectedResult); 48 | MockedDbContext.SaveChanges(); 49 | 50 | Assert.Multiple(() => 51 | { 52 | Assert.That(DbSet.Single(), Is.EqualTo(expectedResult)); 53 | Assert.That(DbSet.Single(), Is.EqualTo(expectedResult)); 54 | }); 55 | } 56 | 57 | [Test] 58 | public virtual void AddAndPersist_Items_AddsAndPersistsItems() 59 | { 60 | var expectedResult = Fixture.CreateMany().ToList(); 61 | 62 | DbSet.AddRange(expectedResult); 63 | MockedDbContext.SaveChanges(); 64 | 65 | var actualResult = DbSet.ToList(); 66 | 67 | Assert.Multiple(() => 68 | { 69 | Assert.That(actualResult, Is.EquivalentTo(expectedResult)); 70 | Assert.That(DbSet.ToList(), Is.EquivalentTo(actualResult)); 71 | }); 72 | } 73 | 74 | [Test] 75 | public virtual async Task AddAndPersistAsync_Item_AddsAndPersistsItem() 76 | { 77 | var expectedResult = Fixture.Create(); 78 | 79 | await DbSet.AddAsync(expectedResult); 80 | await MockedDbContext.SaveChangesAsync(); 81 | 82 | Assert.Multiple(() => 83 | { 84 | Assert.That(DbSet.Single(), Is.EqualTo(expectedResult)); 85 | Assert.That(DbSet.Single(), Is.EqualTo(expectedResult)); 86 | }); 87 | } 88 | 89 | [Test] 90 | public virtual async Task AddAndPersistAsync_Items_AddsAndPersistsItems() 91 | { 92 | var expectedResult = Fixture.CreateMany().ToList(); 93 | 94 | await DbSet.AddRangeAsync(expectedResult); 95 | await MockedDbContext.SaveChangesAsync(); 96 | 97 | var actualResult = DbSet.ToList(); 98 | 99 | Assert.Multiple(() => 100 | { 101 | Assert.That(actualResult, Is.EquivalentTo(expectedResult)); 102 | Assert.That(DbSet.ToList(), Is.EquivalentTo(actualResult)); 103 | }); 104 | } 105 | 106 | [Test] 107 | public virtual void AddThenSingleThenAddRangeThenToListThenWhereThenSelect_ReturnsExpectedResults() 108 | { 109 | var items = Fixture.CreateMany().ToList(); 110 | DbSet.Add(items[0]); 111 | MockedDbContext.SaveChanges(); 112 | 113 | var singleResult = DbSet.Single(); 114 | 115 | DbSet.AddRange(items.Skip(1)); 116 | MockedDbContext.SaveChanges(); 117 | 118 | var toListResult = DbSet.ToList(); 119 | 120 | var selectedItem = items.Last(); 121 | var whereResult = DbSet.Where(x => x.Equals(selectedItem)).ToList(); 122 | 123 | var selectResult = DbSet.Select(x => new { Item = x }).ToList(); 124 | 125 | Assert.Multiple(() => 126 | { 127 | Assert.That(singleResult, Is.EqualTo(items[0])); 128 | Assert.That(toListResult, Is.EquivalentTo(items)); 129 | Assert.That(whereResult, Is.EquivalentTo(new List { selectedItem })); 130 | for (var i = 0; i < items.Count; i++) 131 | { 132 | Assert.That(selectResult[i].Item, Is.EqualTo(items[i])); 133 | } 134 | }); 135 | } 136 | 137 | [Test] 138 | public virtual void AnyThenAddThenPersistThenAny_ReturnsFalseThenTrue() 139 | { 140 | var actualResult1 = DbSet.Any(); 141 | DbSet.Add(Fixture.Create()); 142 | MockedDbContext.SaveChanges(); 143 | var actualResult2 = DbSet.Any(); 144 | 145 | Assert.Multiple(() => 146 | { 147 | Assert.That(actualResult1, Is.False); 148 | Assert.That(actualResult2, Is.True); 149 | }); 150 | } 151 | 152 | [Test] 153 | public virtual async Task AsAsyncEnumerable_ReturnsAsyncEnumerable() 154 | { 155 | var expectedResult = Fixture.Create(); 156 | DbSet.Add(expectedResult); 157 | MockedDbContext.SaveChanges(); 158 | 159 | var asyncEnumerable = DbSet.AsAsyncEnumerable(); 160 | 161 | var actualResults = new List(); 162 | await foreach (var item in asyncEnumerable) 163 | { 164 | actualResults.Add(item); 165 | } 166 | 167 | Assert.Multiple(() => 168 | { 169 | Assert.That(actualResults.Single(), Is.EqualTo(expectedResult)); 170 | Assert.That(actualResults.Single(), Is.EqualTo(expectedResult)); 171 | }); 172 | } 173 | 174 | [Test] 175 | public virtual void AsQueryable_ReturnsQueryable() 176 | { 177 | var expectedResult = Fixture.Create(); 178 | DbSet.Add(expectedResult); 179 | MockedDbContext.SaveChanges(); 180 | 181 | var queryable = DbSet.AsQueryable(); 182 | 183 | Assert.Multiple(() => 184 | { 185 | Assert.That(queryable.Single(), Is.EqualTo(expectedResult)); 186 | Assert.That(queryable.Single(), Is.EqualTo(expectedResult)); 187 | }); 188 | } 189 | } 190 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.NSubstitute/Helpers/NoSetUpHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using System.Threading; 6 | using EntityFrameworkCore.Testing.Common; 7 | using EntityFrameworkCore.Testing.NSubstitute.Extensions; 8 | using Microsoft.EntityFrameworkCore; 9 | using Microsoft.EntityFrameworkCore.Metadata; 10 | using Microsoft.Extensions.Logging; 11 | using NSubstitute; 12 | using NSubstitute.Core; 13 | using NSubstitute.Extensions; 14 | using rgvlee.Core.Common.Extensions; 15 | using rgvlee.Core.Common.Helpers; 16 | 17 | namespace EntityFrameworkCore.Testing.NSubstitute.Helpers 18 | { 19 | internal class NoSetUpHandler : ICallHandler where TDbContext : DbContext 20 | { 21 | private static readonly ILogger> Logger = LoggingHelper.CreateLogger>(); 22 | 23 | private readonly List _allModelEntityTypes; 24 | 25 | private readonly TDbContext _dbContext; 26 | 27 | private readonly List _dbContextModelProperties; 28 | 29 | public NoSetUpHandler(TDbContext dbContext) 30 | { 31 | _dbContext = dbContext; 32 | _allModelEntityTypes = _dbContext.Model.GetEntityTypes().ToList(); 33 | _dbContextModelProperties = _dbContext.GetType() 34 | .GetProperties() 35 | .Where(x => x.PropertyType.IsGenericType && x.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>)) 36 | .ToList(); 37 | } 38 | 39 | public RouteAction Handle(ICall call) 40 | { 41 | var mockedDbContext = call.Target(); 42 | var invokedMethod = call.GetMethodInfo(); 43 | var arguments = call.GetArguments(); 44 | 45 | var modelType = GetModelType(invokedMethod); 46 | if (modelType == null) 47 | { 48 | return invokedMethod.ReturnType != typeof(void) ? RouteAction.Return(invokedMethod.ReturnType.GetDefaultValue()) : RouteAction.Continue(); 49 | } 50 | 51 | Logger.LogDebug("Setting up model '{type}'", modelType); 52 | 53 | var modelEntityType = _allModelEntityTypes.SingleOrDefault(x => x.ClrType.Equals(modelType)); 54 | if (modelEntityType == null) 55 | { 56 | throw new InvalidOperationException(string.Format(ExceptionMessages.CannotCreateDbSetTypeNotIncludedInModel, 57 | invokedMethod.GetGenericArguments().Single().Name)); 58 | } 59 | 60 | var setUpModelMethod = typeof(NoSetUpHandler).GetMethods(BindingFlags.Instance | BindingFlags.NonPublic) 61 | .Single(x => x.Name.Equals(modelEntityType.FindPrimaryKey() != null ? "SetUpModel" : "SetUpReadOnlyModel")); 62 | 63 | setUpModelMethod.MakeGenericMethod(modelType).Invoke(this, new[] { mockedDbContext }); 64 | 65 | return RouteAction.Return(invokedMethod.Invoke(mockedDbContext, arguments?.ToArray())); 66 | } 67 | 68 | private Type GetModelType(MethodInfo invokedMethod) 69 | { 70 | var dbContextModelProperty = _dbContextModelProperties.SingleOrDefault(x => x.GetMethod.Name.Equals(invokedMethod.Name)); 71 | if (dbContextModelProperty != null) 72 | { 73 | return dbContextModelProperty.PropertyType.GetGenericArguments().Single(); 74 | } 75 | 76 | if (!invokedMethod.IsGenericMethod) 77 | { 78 | return null; 79 | } 80 | 81 | var dbContextMethod = typeof(DbContext).GetMethods(BindingFlags.Instance | BindingFlags.Public) 82 | .SingleOrDefault(x => x.IsGenericMethod && x.GetGenericMethodDefinition().Equals(invokedMethod.GetGenericMethodDefinition())); 83 | 84 | if (dbContextMethod != null) 85 | { 86 | return invokedMethod.GetGenericArguments().Single(); 87 | } 88 | 89 | return null; 90 | } 91 | 92 | private void SetUpModel(TDbContext mockedDbContext) where TEntity : class 93 | { 94 | var mockedDbSet = _dbContext.Set().CreateMockedDbSet(); 95 | 96 | var property = typeof(TDbContext).GetProperties().SingleOrDefault(p => p.PropertyType == typeof(DbSet)); 97 | 98 | if (property != null) 99 | { 100 | property.GetValue(mockedDbContext.Configure()).Returns(callInfo => mockedDbSet); 101 | } 102 | else 103 | { 104 | Logger.LogDebug("Could not find a DbContext property for type '{type}'", typeof(TEntity)); 105 | } 106 | 107 | mockedDbContext.Configure().Set().Returns(callInfo => mockedDbSet); 108 | 109 | mockedDbContext.Add(Arg.Any()).Returns(callInfo => _dbContext.Add(callInfo.Arg())); 110 | mockedDbContext.AddAsync(Arg.Any(), Arg.Any()) 111 | .Returns(callInfo => _dbContext.AddAsync(callInfo.Arg(), callInfo.Arg())); 112 | 113 | mockedDbContext.Attach(Arg.Any()).Returns(callInfo => _dbContext.Attach(callInfo.Arg())); 114 | 115 | mockedDbContext.Entry(Arg.Any()).Returns(callInfo => _dbContext.Entry(callInfo.Arg())); 116 | 117 | mockedDbContext.Find(Arg.Any()).Returns(callInfo => _dbContext.Find(callInfo.Arg())); 118 | 119 | mockedDbContext.FindAsync(Arg.Any()).Returns(callInfo => _dbContext.FindAsync(callInfo.Arg())); 120 | mockedDbContext.FindAsync(Arg.Any(), Arg.Any()) 121 | .Returns(callInfo => _dbContext.FindAsync(callInfo.Arg(), callInfo.Arg())); 122 | 123 | mockedDbContext.Remove(Arg.Any()).Returns(callInfo => _dbContext.Remove(callInfo.Arg())); 124 | 125 | mockedDbContext.Update(Arg.Any()).Returns(callInfo => _dbContext.Update(callInfo.Arg())); 126 | } 127 | 128 | private void SetUpReadOnlyModel(TDbContext mockedDbContext) where TEntity : class 129 | { 130 | var mockedReadOnlyDbSet = _dbContext.Set().CreateMockedReadOnlyDbSet(); 131 | 132 | var property = typeof(TDbContext).GetProperties().SingleOrDefault(p => p.PropertyType == typeof(DbSet)); 133 | if (property != null) 134 | { 135 | property.GetValue(mockedDbContext.Configure()).Returns(callInfo => mockedReadOnlyDbSet); 136 | } 137 | else 138 | { 139 | Logger.LogDebug("Could not find a DbContext property for type '{type}'", typeof(TEntity)); 140 | } 141 | 142 | mockedDbContext.Configure().Set().Returns(callInfo => mockedReadOnlyDbSet); 143 | } 144 | } 145 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015/2017 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # Visual Studio 2017 auto generated files 33 | Generated\ Files/ 34 | 35 | # MSTest test Results 36 | [Tt]est[Rr]esult*/ 37 | [Bb]uild[Ll]og.* 38 | 39 | # NUNIT 40 | *.VisualState.xml 41 | TestResult.xml 42 | 43 | # Build Results of an ATL Project 44 | [Dd]ebugPS/ 45 | [Rr]eleasePS/ 46 | dlldata.c 47 | 48 | # Benchmark Results 49 | BenchmarkDotNet.Artifacts/ 50 | 51 | # .NET Core 52 | project.lock.json 53 | project.fragment.lock.json 54 | artifacts/ 55 | **/Properties/launchSettings.json 56 | 57 | # StyleCop 58 | StyleCopReport.xml 59 | 60 | # Files built by Visual Studio 61 | *_i.c 62 | *_p.c 63 | *_i.h 64 | *.ilk 65 | *.meta 66 | *.obj 67 | *.iobj 68 | *.pch 69 | *.pdb 70 | *.ipdb 71 | *.pgc 72 | *.pgd 73 | *.rsp 74 | *.sbr 75 | *.tlb 76 | *.tli 77 | *.tlh 78 | *.tmp 79 | *.tmp_proj 80 | *.log 81 | *.vspscc 82 | *.vssscc 83 | .builds 84 | *.pidb 85 | *.svclog 86 | *.scc 87 | 88 | # Chutzpah Test files 89 | _Chutzpah* 90 | 91 | # Visual C++ cache files 92 | ipch/ 93 | *.aps 94 | *.ncb 95 | *.opendb 96 | *.opensdf 97 | *.sdf 98 | *.cachefile 99 | *.VC.db 100 | *.VC.VC.opendb 101 | 102 | # Visual Studio profiler 103 | *.psess 104 | *.vsp 105 | *.vspx 106 | *.sap 107 | 108 | # Visual Studio Trace Files 109 | *.e2e 110 | 111 | # TFS 2012 Local Workspace 112 | $tf/ 113 | 114 | # Guidance Automation Toolkit 115 | *.gpState 116 | 117 | # ReSharper is a .NET coding add-in 118 | _ReSharper*/ 119 | *.[Rr]e[Ss]harper 120 | *.DotSettings.user 121 | 122 | # JustCode is a .NET coding add-in 123 | .JustCode 124 | 125 | # TeamCity is a build add-in 126 | _TeamCity* 127 | 128 | # DotCover is a Code Coverage Tool 129 | *.dotCover 130 | 131 | # AxoCover is a Code Coverage Tool 132 | .axoCover/* 133 | !.axoCover/settings.json 134 | 135 | # Visual Studio code coverage results 136 | *.coverage 137 | *.coveragexml 138 | 139 | # NCrunch 140 | _NCrunch_* 141 | .*crunch*.local.xml 142 | nCrunchTemp_* 143 | 144 | # MightyMoose 145 | *.mm.* 146 | AutoTest.Net/ 147 | 148 | # Web workbench (sass) 149 | .sass-cache/ 150 | 151 | # Installshield output folder 152 | [Ee]xpress/ 153 | 154 | # DocProject is a documentation generator add-in 155 | DocProject/buildhelp/ 156 | DocProject/Help/*.HxT 157 | DocProject/Help/*.HxC 158 | DocProject/Help/*.hhc 159 | DocProject/Help/*.hhk 160 | DocProject/Help/*.hhp 161 | DocProject/Help/Html2 162 | DocProject/Help/html 163 | 164 | # Click-Once directory 165 | publish/ 166 | 167 | # Publish Web Output 168 | *.[Pp]ublish.xml 169 | *.azurePubxml 170 | # Note: Comment the next line if you want to checkin your web deploy settings, 171 | # but database connection strings (with potential passwords) will be unencrypted 172 | *.pubxml 173 | *.publishproj 174 | 175 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 176 | # checkin your Azure Web App publish settings, but sensitive information contained 177 | # in these scripts will be unencrypted 178 | PublishScripts/ 179 | 180 | # NuGet Packages 181 | *.nupkg 182 | # The packages folder can be ignored because of Package Restore 183 | **/[Pp]ackages/* 184 | # except build/, which is used as an MSBuild target. 185 | !**/[Pp]ackages/build/ 186 | # Uncomment if necessary however generally it will be regenerated when needed 187 | #!**/[Pp]ackages/repositories.config 188 | # NuGet v3's project.json files produces more ignorable files 189 | *.nuget.props 190 | *.nuget.targets 191 | 192 | # Microsoft Azure Build Output 193 | csx/ 194 | *.build.csdef 195 | 196 | # Microsoft Azure Emulator 197 | ecf/ 198 | rcf/ 199 | 200 | # Windows Store app package directories and files 201 | AppPackages/ 202 | BundleArtifacts/ 203 | Package.StoreAssociation.xml 204 | _pkginfo.txt 205 | *.appx 206 | 207 | # Visual Studio cache files 208 | # files ending in .cache can be ignored 209 | *.[Cc]ache 210 | # but keep track of directories ending in .cache 211 | !*.[Cc]ache/ 212 | 213 | # Others 214 | ClientBin/ 215 | ~$* 216 | *~ 217 | *.dbmdl 218 | *.dbproj.schemaview 219 | *.jfm 220 | *.pfx 221 | *.publishsettings 222 | orleans.codegen.cs 223 | 224 | # Including strong name files can present a security risk 225 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 226 | #*.snk 227 | 228 | # Since there are multiple workflows, uncomment next line to ignore bower_components 229 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 230 | #bower_components/ 231 | 232 | # RIA/Silverlight projects 233 | Generated_Code/ 234 | 235 | # Backup & report files from converting an old project file 236 | # to a newer Visual Studio version. Backup files are not needed, 237 | # because we have git ;-) 238 | _UpgradeReport_Files/ 239 | Backup*/ 240 | UpgradeLog*.XML 241 | UpgradeLog*.htm 242 | ServiceFabricBackup/ 243 | *.rptproj.bak 244 | 245 | # SQL Server files 246 | *.mdf 247 | *.ldf 248 | *.ndf 249 | 250 | # Business Intelligence projects 251 | *.rdl.data 252 | *.bim.layout 253 | *.bim_*.settings 254 | *.rptproj.rsuser 255 | 256 | # Microsoft Fakes 257 | FakesAssemblies/ 258 | 259 | # GhostDoc plugin setting file 260 | *.GhostDoc.xml 261 | 262 | # Node.js Tools for Visual Studio 263 | .ntvs_analysis.dat 264 | node_modules/ 265 | 266 | # Visual Studio 6 build log 267 | *.plg 268 | 269 | # Visual Studio 6 workspace options file 270 | *.opt 271 | 272 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 273 | *.vbw 274 | 275 | # Visual Studio LightSwitch build output 276 | **/*.HTMLClient/GeneratedArtifacts 277 | **/*.DesktopClient/GeneratedArtifacts 278 | **/*.DesktopClient/ModelManifest.xml 279 | **/*.Server/GeneratedArtifacts 280 | **/*.Server/ModelManifest.xml 281 | _Pvt_Extensions 282 | 283 | # Paket dependency manager 284 | .paket/paket.exe 285 | paket-files/ 286 | 287 | # FAKE - F# Make 288 | .fake/ 289 | 290 | # JetBrains Rider 291 | .idea/ 292 | *.sln.iml 293 | 294 | # CodeRush 295 | .cr/ 296 | 297 | # Python Tools for Visual Studio (PTVS) 298 | __pycache__/ 299 | *.pyc 300 | 301 | # Cake - Uncomment if you are using it 302 | # tools/** 303 | # !tools/packages.config 304 | 305 | # Tabs Studio 306 | *.tss 307 | 308 | # Telerik's JustMock configuration file 309 | *.jmconfig 310 | 311 | # BizTalk build output 312 | *.btp.cs 313 | *.btm.cs 314 | *.odx.cs 315 | *.xsd.cs 316 | 317 | # OpenCover UI analysis results 318 | OpenCover/ 319 | 320 | # Azure Stream Analytics local run output 321 | ASALocalRun/ 322 | 323 | # MSBuild Binary and Structured Log 324 | *.binlog 325 | 326 | # NVidia Nsight GPU debugger configuration file 327 | *.nvuser 328 | 329 | # MFractors (Xamarin productivity tool) working folder 330 | .mfractor/ 331 | -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Common/Helpers/ParameterMatchingHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data; 4 | using System.Data.Common; 5 | using System.Linq; 6 | using System.Text; 7 | using Microsoft.Extensions.Logging; 8 | using rgvlee.Core.Common.Helpers; 9 | 10 | namespace EntityFrameworkCore.Testing.Common.Helpers 11 | { 12 | /// 13 | /// A helper for parameter matching. 14 | /// 15 | public class ParameterMatchingHelper 16 | { 17 | private static readonly ILogger Logger = LoggingHelper.CreateLogger(typeof(ParameterMatchingHelper)); 18 | 19 | /// 20 | /// Determines whether the invocation parameters match the set up parameters. 21 | /// 22 | /// The set up parameters. 23 | /// The invocation parameters. 24 | /// true the invocation parameters are a partial or full match of the set up parameters. 25 | /// 26 | /// If the parameters are DbParameters, parameter name and value are compared. 27 | /// Parameter name matching is case insensitive. 28 | /// If the value is a string, the matching is case insensitive. 29 | /// For everything else an exact match is required. 30 | /// 31 | public static bool DoInvocationParametersMatchSetUpParameters(IEnumerable setUpParameters, IEnumerable invocationParameters) 32 | { 33 | var setUpParametersAsList = setUpParameters.ToList(); 34 | var invocationParametersAsList = invocationParameters.ToList(); 35 | 36 | var matches = new Dictionary(); 37 | for (var i = 0; i < invocationParametersAsList.Count; i++) 38 | { 39 | var invocationParameter = invocationParametersAsList[i]; 40 | Logger.LogDebug("Checking invocationParameter '{invocationParameter}'", invocationParameter); 41 | matches.Add(i, -1); 42 | 43 | //What was the last set up parameter matched? 44 | var startAt = matches.Any() ? matches.Max(x => x.Value) + 1 : 0; 45 | Logger.LogDebug("startAt: {startAt}", startAt); 46 | 47 | for (var j = 0; j < setUpParametersAsList.Count; j++) 48 | { 49 | var setUpParameter = setUpParametersAsList[j]; 50 | Logger.LogDebug("Checking setUpParameter '{setUpParameter}'", setUpParameter); 51 | 52 | if (invocationParameter is DbParameter dbInvocationParameter && 53 | setUpParameter is DbParameter dbSetUpParameter && 54 | DoesInvocationParameterMatchSetUpParameter(dbSetUpParameter, dbInvocationParameter)) 55 | { 56 | matches[i] = j; 57 | break; 58 | } 59 | 60 | if (DoesInvocationParameterValueMatchSetUpParameterValue(setUpParameter, invocationParameter)) 61 | { 62 | matches[i] = j; 63 | break; 64 | } 65 | } 66 | } 67 | 68 | Logger.LogDebug("Match summary '{summary}'", string.Join(Environment.NewLine, matches.Select(x => $"{x.Key}: {x.Value}"))); 69 | 70 | return matches.Count(x => x.Value > -1) >= setUpParametersAsList.Count; 71 | } 72 | 73 | private static bool DoesInvocationParameterValueMatchSetUpParameterValue(object setUpParameter, object invocationParameter) 74 | { 75 | if (invocationParameter == setUpParameter) 76 | { 77 | return true; 78 | } 79 | 80 | if (invocationParameter != null && setUpParameter != null && invocationParameter.Equals(setUpParameter)) 81 | { 82 | return true; 83 | } 84 | 85 | if (invocationParameter is string stringInvocationParameterValue && 86 | setUpParameter is string stringSetUpParameterValue && 87 | stringInvocationParameterValue.Equals(stringSetUpParameterValue, StringComparison.OrdinalIgnoreCase)) 88 | { 89 | return true; 90 | } 91 | 92 | return false; 93 | } 94 | 95 | private static bool DoesInvocationParameterMatchSetUpParameter(IDataParameter setUpParameter, IDataParameter invocationParameter) 96 | { 97 | var setUpParameterParameterName = setUpParameter.ParameterName ?? string.Empty; 98 | var invocationParameterParameterName = invocationParameter.ParameterName ?? string.Empty; 99 | 100 | if (!invocationParameterParameterName.Equals(setUpParameterParameterName, StringComparison.OrdinalIgnoreCase)) 101 | { 102 | return false; 103 | } 104 | 105 | return DoesInvocationParameterValueMatchSetUpParameterValue(setUpParameter.Value, invocationParameter.Value); 106 | } 107 | 108 | /// 109 | /// Converts a sequence of invocation parameters to a string of parameter names and values. 110 | /// 111 | /// The invocation parameters. 112 | /// A string of parameter names and values. 113 | public static string StringifyParameters(IEnumerable invocationParameters) 114 | { 115 | var invocationParametersAsList = invocationParameters.ToList(); 116 | var parts = new List(); 117 | for (var i = 0; i < invocationParametersAsList.Count; i++) 118 | { 119 | var invocationParameter = invocationParametersAsList[i]; 120 | 121 | var sb = new StringBuilder(); 122 | switch (invocationParameter) 123 | { 124 | case DbParameter dbInvocationParameter: 125 | { 126 | sb.Append(dbInvocationParameter.ParameterName); 127 | sb.Append(": "); 128 | if (dbInvocationParameter.Value == null) 129 | { 130 | sb.Append("null"); 131 | } 132 | else 133 | { 134 | sb.Append(dbInvocationParameter.Value); 135 | } 136 | 137 | break; 138 | } 139 | 140 | case null: 141 | sb.Append("Parameter "); 142 | sb.Append(i); 143 | sb.Append(": null"); 144 | break; 145 | 146 | default: 147 | sb.Append("Parameter "); 148 | sb.Append(i); 149 | sb.Append(": "); 150 | sb.Append(invocationParameter); 151 | break; 152 | } 153 | 154 | parts.Add(sb.ToString()); 155 | } 156 | 157 | return string.Join(Environment.NewLine, parts); 158 | } 159 | } 160 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Common.Tests/BaseForReadOnlyDbSetTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Microsoft.Data.SqlClient; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using AutoFixture; 7 | using Microsoft.EntityFrameworkCore; 8 | using NUnit.Framework; 9 | 10 | namespace EntityFrameworkCore.Testing.Common.Tests 11 | { 12 | public abstract class BaseForReadOnlyDbSetTests : BaseForMockedQueryableTests where TEntity : BaseTestEntity 13 | { 14 | protected override void SeedQueryableSource() 15 | { 16 | var itemsToAdd = Fixture.Build().With(p => p.CreatedAt, DateTime.Today).With(p => p.LastModifiedAt, DateTime.Today).CreateMany().ToList(); 17 | AddRangeToReadOnlySource(DbSet, itemsToAdd); 18 | //MockedDbContext.SaveChanges(); 19 | ItemsAddedToQueryableSource = itemsToAdd; 20 | } 21 | 22 | protected abstract void AddToReadOnlySource(DbSet mockedDbQuery, TEntity item); 23 | 24 | protected abstract void AddRangeToReadOnlySource(DbSet mockedDbQuery, IEnumerable items); 25 | 26 | protected abstract void ClearReadOnlySource(DbSet mockedDbQuery); 27 | 28 | [Test] 29 | public virtual void AddRangeToReadOnlySource_Items_AddsItemsToReadOnlySource() 30 | { 31 | var expectedResult = Fixture.CreateMany().ToList(); 32 | 33 | AddRangeToReadOnlySource(DbSet, expectedResult); 34 | 35 | Assert.That(DbSet, Is.EquivalentTo(expectedResult)); 36 | } 37 | 38 | [Test] 39 | public virtual void AddRangeToReadOnlySourceThenAddRangeToReadOnlySource_Items_AddsAllItemsToReadOnlySource() 40 | { 41 | var expectedResult = Fixture.CreateMany(4).ToList(); 42 | 43 | AddRangeToReadOnlySource(DbSet, expectedResult.Take(2)); 44 | AddRangeToReadOnlySource(DbSet, expectedResult.Skip(2)); 45 | 46 | Assert.That(DbSet, Is.EquivalentTo(expectedResult)); 47 | } 48 | 49 | [Test] 50 | public virtual void AddToReadOnlySource_Item_AddsItemToReadOnlySource() 51 | { 52 | var expectedResult = Fixture.Create(); 53 | 54 | AddToReadOnlySource(DbSet, expectedResult); 55 | var numberOfItemsAdded = DbSet.ToList().Count; 56 | 57 | Assert.That(numberOfItemsAdded, Is.EqualTo(1)); 58 | } 59 | 60 | [Test] 61 | public virtual void AddToReadOnlySourceThenAddToReadOnlySource_Items_AddsBothItemsToReadOnlySource() 62 | { 63 | var expectedResult = Fixture.CreateMany(2).ToList(); 64 | 65 | AddToReadOnlySource(DbSet, expectedResult.First()); 66 | AddToReadOnlySource(DbSet, expectedResult.Last()); 67 | 68 | Assert.That(DbSet, Is.EquivalentTo(expectedResult)); 69 | } 70 | 71 | [Test] 72 | public virtual void AnyThenAddToReadOnlySourceThenAny_ReturnsFalseThenTrue() 73 | { 74 | var actualResult1 = DbSet.Any(); 75 | AddToReadOnlySource(DbSet, Fixture.Create()); 76 | var actualResult2 = DbSet.Any(); 77 | 78 | Assert.Multiple(() => 79 | { 80 | Assert.That(actualResult1, Is.False); 81 | Assert.That(actualResult2, Is.True); 82 | }); 83 | } 84 | 85 | [Test] 86 | public virtual async Task AsAsyncEnumerable_ReturnsAsyncEnumerable() 87 | { 88 | var expectedResult = Fixture.Create(); 89 | AddToReadOnlySource(DbSet, expectedResult); 90 | 91 | var asyncEnumerable = DbSet.AsAsyncEnumerable(); 92 | 93 | var actualResults = new List(); 94 | await foreach (var item in asyncEnumerable) 95 | { 96 | actualResults.Add(item); 97 | } 98 | 99 | Assert.Multiple(() => 100 | { 101 | Assert.That(actualResults.Single(), Is.EqualTo(expectedResult)); 102 | Assert.That(actualResults.Single(), Is.EqualTo(expectedResult)); 103 | }); 104 | } 105 | 106 | [Test] 107 | public virtual void AsQueryable_ReturnsQueryable() 108 | { 109 | var expectedResult = Fixture.Create(); 110 | AddToReadOnlySource(DbSet, expectedResult); 111 | 112 | var queryable = DbSet.AsQueryable(); 113 | 114 | Assert.Multiple(() => 115 | { 116 | Assert.That(queryable.Single(), Is.EqualTo(expectedResult)); 117 | Assert.That(queryable.Single(), Is.EqualTo(expectedResult)); 118 | }); 119 | } 120 | 121 | [Test] 122 | public virtual void ClearReadOnlySource_WithNoItemsAddedToReadOnlySource_DoesNothing() 123 | { 124 | var preActNumberOfItems = DbSet.ToList().Count; 125 | 126 | ClearReadOnlySource(DbSet); 127 | 128 | var postActNumberOfItems = DbSet.ToList().Count; 129 | Assert.Multiple(() => 130 | { 131 | Assert.That(preActNumberOfItems, Is.EqualTo(0)); 132 | Assert.That(postActNumberOfItems, Is.EqualTo(preActNumberOfItems)); 133 | }); 134 | } 135 | 136 | [Test] 137 | public virtual void ClearReadOnlySourceWithExistingItems_RemovesAllItemsFromReadOnlySource() 138 | { 139 | var expectedResult = Fixture.CreateMany().ToList(); 140 | AddRangeToReadOnlySource(DbSet, expectedResult); 141 | var numberOfItemsAdded = DbSet.ToList().Count; 142 | 143 | ClearReadOnlySource(DbSet); 144 | 145 | Assert.Multiple(() => 146 | { 147 | Assert.That(numberOfItemsAdded, Is.EqualTo(expectedResult.Count)); 148 | Assert.That(DbSet.Any(), Is.False); 149 | }); 150 | } 151 | 152 | [Test] 153 | public override void FromSqlRaw_QueryProviderWithManyFromSqlResults_ReturnsExpectedResults() 154 | { 155 | var sql1 = "sp_NoParams"; 156 | var expectedResult1 = Fixture.CreateMany().ToList(); 157 | 158 | var sql2 = "sp_WithParams"; 159 | var parameters2 = new List { new("@SomeParameter1", "Value1"), new("@SomeParameter2", "Value2") }; 160 | var expectedResult2 = Fixture.CreateMany().ToList(); 161 | 162 | AddFromSqlRawResult(DbSet, sql1, expectedResult1); 163 | 164 | //Change the source, this will force the query provider mock to aggregate 165 | AddRangeToReadOnlySource(DbSet, Fixture.CreateMany().ToList()); 166 | 167 | AddFromSqlRawResult(DbSet, sql2, parameters2, expectedResult2); 168 | 169 | Console.WriteLine("actualResult1"); 170 | var actualResult1 = DbSet.FromSqlRaw("[dbo].[sp_NoParams]").ToList(); 171 | 172 | Console.WriteLine("actualResult2"); 173 | var actualResult2 = DbSet.FromSqlRaw("[dbo].[sp_WithParams]", parameters2.ToArray()).ToList(); 174 | 175 | Assert.Multiple(() => 176 | { 177 | Assert.That(actualResult1, Is.EquivalentTo(expectedResult1)); 178 | Assert.That(actualResult2, Is.EquivalentTo(expectedResult2)); 179 | }); 180 | } 181 | } 182 | } -------------------------------------------------------------------------------- /src/EntityFrameworkCore.Testing.Common.Tests/ReadOnlyDbSetExceptionTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using AutoFixture; 3 | using Microsoft.EntityFrameworkCore; 4 | using NUnit.Framework; 5 | 6 | namespace EntityFrameworkCore.Testing.Common.Tests 7 | { 8 | public abstract class ReadOnlyDbSetExceptionTests : BaseForTests where TEntity : BaseTestEntity 9 | { 10 | protected abstract DbSet DbSet { get; } 11 | 12 | [Test] 13 | public void Add_Item_ThrowsException() 14 | { 15 | var ex = Assert.Throws(() => 16 | { 17 | DbSet.Add(Fixture.Create()); 18 | }); 19 | Assert.That(ex.Message, 20 | Is.EqualTo( 21 | $"Unable to track an instance of type '{typeof(TEntity).Name}' because it does not have a primary key. Only entity types with a primary key may be tracked.")); 22 | } 23 | 24 | [Test] 25 | public void AddAsync_Item_ThrowsException() 26 | { 27 | var ex = Assert.ThrowsAsync(async () => 28 | { 29 | await DbSet.AddAsync(Fixture.Create()); 30 | }); 31 | Assert.That(ex.Message, 32 | Is.EqualTo( 33 | $"Unable to track an instance of type '{typeof(TEntity).Name}' because it does not have a primary key. Only entity types with a primary key may be tracked.")); 34 | } 35 | 36 | [Test] 37 | public void AddRange_Items_ThrowsException() 38 | { 39 | var ex = Assert.Throws(() => 40 | { 41 | DbSet.AddRange(Fixture.CreateMany()); 42 | }); 43 | Assert.That(ex.Message, 44 | Is.EqualTo( 45 | $"Unable to track an instance of type '{typeof(TEntity).Name}' because it does not have a primary key. Only entity types with a primary key may be tracked.")); 46 | } 47 | 48 | [Test] 49 | public void AddRangeAsync_Items_ThrowsException() 50 | { 51 | var ex = Assert.ThrowsAsync(async () => 52 | { 53 | await DbSet.AddRangeAsync(Fixture.CreateMany()); 54 | }); 55 | Assert.That(ex.Message, 56 | Is.EqualTo( 57 | $"Unable to track an instance of type '{typeof(TEntity).Name}' because it does not have a primary key. Only entity types with a primary key may be tracked.")); 58 | } 59 | 60 | [Test] 61 | public void Attach_Item_ThrowsException() 62 | { 63 | var ex = Assert.Throws(() => 64 | { 65 | DbSet.Attach(Fixture.Create()); 66 | }); 67 | Assert.That(ex.Message, 68 | Is.EqualTo( 69 | $"Unable to track an instance of type '{typeof(TEntity).Name}' because it does not have a primary key. Only entity types with a primary key may be tracked.")); 70 | } 71 | 72 | [Test] 73 | public void AttachRange_Items_ThrowsException() 74 | { 75 | var ex = Assert.Throws(() => 76 | { 77 | DbSet.AttachRange(Fixture.CreateMany()); 78 | }); 79 | Assert.That(ex.Message, 80 | Is.EqualTo( 81 | $"Unable to track an instance of type '{typeof(TEntity).Name}' because it does not have a primary key. Only entity types with a primary key may be tracked.")); 82 | } 83 | 84 | [Test] 85 | public void Find_Item_ThrowsException() 86 | { 87 | var itemToFind = Fixture.Create(); 88 | var ex = Assert.Throws(() => 89 | { 90 | DbSet.Find(itemToFind.Id); 91 | }); 92 | Assert.That(ex.Message, Is.EqualTo($"The invoked method cannot be used for the entity type '{typeof(TEntity).Name}' because it does not have a primary key. For more information on keyless entity types, see https://go.microsoft.com/fwlink/?linkid=2141943.")); 93 | } 94 | 95 | [Test] 96 | public void Find_Items_ThrowsException() 97 | { 98 | var itemsToFind = Fixture.CreateMany(); 99 | var ex = Assert.ThrowsAsync(async () => 100 | { 101 | await DbSet.FindAsync(itemsToFind); 102 | }); 103 | Assert.That(ex.Message, Is.EqualTo($"The invoked method cannot be used for the entity type '{typeof(TEntity).Name}' because it does not have a primary key. For more information on keyless entity types, see https://go.microsoft.com/fwlink/?linkid=2141943.")); 104 | } 105 | 106 | [Test] 107 | public void Local_ThrowsException() 108 | { 109 | var ex = Assert.Throws(() => 110 | { 111 | var localView = DbSet.Local; 112 | }); 113 | Assert.That(ex.Message, Is.EqualTo($"The invoked method cannot be used for the entity type '{typeof(TEntity).Name}' because it does not have a primary key. For more information on keyless entity types, see https://go.microsoft.com/fwlink/?linkid=2141943.")); 114 | } 115 | 116 | [Test] 117 | public void Remove_Item_ThrowsException() 118 | { 119 | var ex = Assert.Throws(() => 120 | { 121 | DbSet.Remove(Fixture.Create()); 122 | }); 123 | Assert.That(ex.Message, 124 | Is.EqualTo( 125 | $"Unable to track an instance of type '{typeof(TEntity).Name}' because it does not have a primary key. Only entity types with a primary key may be tracked.")); 126 | } 127 | 128 | [Test] 129 | public void RemoveRange_Items_ThrowsException() 130 | { 131 | var ex = Assert.Throws(() => 132 | { 133 | DbSet.RemoveRange(Fixture.CreateMany()); 134 | }); 135 | Assert.That(ex.Message, 136 | Is.EqualTo( 137 | $"Unable to track an instance of type '{typeof(TEntity).Name}' because it does not have a primary key. Only entity types with a primary key may be tracked.")); 138 | } 139 | 140 | [Test] 141 | public void Update_Item_ThrowsException() 142 | { 143 | var ex = Assert.Throws(() => 144 | { 145 | DbSet.Update(Fixture.Create()); 146 | }); 147 | Assert.That(ex.Message, 148 | Is.EqualTo( 149 | $"Unable to track an instance of type '{typeof(TEntity).Name}' because it does not have a primary key. Only entity types with a primary key may be tracked.")); 150 | } 151 | 152 | [Test] 153 | public void UpdateRange_Items_ThrowsException() 154 | { 155 | var ex = Assert.Throws(() => 156 | { 157 | DbSet.UpdateRange(Fixture.CreateMany()); 158 | }); 159 | Assert.That(ex.Message, 160 | Is.EqualTo( 161 | $"Unable to track an instance of type '{typeof(TEntity).Name}' because it does not have a primary key. Only entity types with a primary key may be tracked.")); 162 | } 163 | } 164 | } --------------------------------------------------------------------------------