Repository: rgvlee/EntityFrameworkCore.Testing Branch: 10.x Commit: 648c8656557b Files: 122 Total size: 400.2 KB Directory structure: gitextract_5vjkh0op/ ├── .github/ │ └── workflows/ │ ├── continuous-integration-checks.yml │ └── release.yml ├── .gitignore ├── EntityFrameworkCore.Testing.Moq.nuspec ├── EntityFrameworkCore.Testing.NSubstitute.nuspec ├── EntityFrameworkCore.Testing.sln ├── LICENSE ├── README.md ├── TODO.md ├── googlea6bd68d4a55b1e59.html └── src/ ├── EntityFrameworkCore.DefaultBehaviour.Tests/ │ ├── ByTypeDbSetTests.cs │ ├── ByTypeReadOnlyDbSetExceptionTests.cs │ ├── ByTypeReadOnlyDbSetTests.cs │ ├── DbContextTests.cs │ ├── EntityFrameworkCore.DefaultBehaviour.Tests.csproj │ ├── Issue114Tests.cs │ ├── Issue117Tests.cs │ ├── Issue49Tests.cs │ └── Issue88Tests.cs ├── EntityFrameworkCore.Testing.Common/ │ ├── AsyncEnumerable.cs │ ├── AsyncEnumerator.cs │ ├── AsyncQueryProvider.cs │ ├── EntityFrameworkCore.Testing.Common.csproj │ ├── EntityFrameworkCore.Testing.Common.xml │ ├── ExceptionMessages.Designer.cs │ ├── ExceptionMessages.resx │ ├── Helpers/ │ │ ├── BaseMockedDbContextBuilder.cs │ │ ├── BaseMockedDbContextFactory.cs │ │ ├── ExpressionHelper.cs │ │ ├── IMockedDbContextBuilder.cs │ │ ├── MockedDbContextFactoryOptions.cs │ │ └── ParameterMatchingHelper.cs │ └── QueryRootExpression.cs ├── EntityFrameworkCore.Testing.Common.Tests/ │ ├── AsyncEnumerableTests.cs │ ├── BaseForDbContextTests.cs │ ├── BaseForDbSetTests.cs │ ├── BaseForMockedQueryableTests.cs │ ├── BaseForQueryableTests.cs │ ├── BaseForReadOnlyDbSetTests.cs │ ├── BaseForTests.cs │ ├── BaseTestEntity.cs │ ├── EntityFrameworkCore.Testing.Common.Tests.csproj │ ├── Issue114Tests.cs │ ├── Issue117Tests.cs │ ├── Issue126Tests.cs │ ├── Issue49Tests.cs │ ├── Issue88Tests.cs │ ├── MappingProfile.cs │ ├── NotRegisteredEntity.cs │ ├── ReadOnlyDbSetExceptionTests.cs │ ├── TestDbContext.cs │ ├── TestEntity.cs │ ├── TestReadOnlyEntity.cs │ └── TestViewModel.cs ├── EntityFrameworkCore.Testing.Moq/ │ ├── Create.cs │ ├── EntityFrameworkCore.Testing.Moq.csproj │ ├── EntityFrameworkCore.Testing.Moq.xml │ ├── Extensions/ │ │ ├── DbContextExtensions.cs │ │ ├── DbSetExtensions.Internal.cs │ │ ├── QueryProviderExtensions.Internal.cs │ │ ├── QueryProviderExtensions.cs │ │ ├── QueryableExtensions.cs │ │ ├── ReadOnlyDbSetExtensions.Internal.cs │ │ └── ReadOnlyDbSetExtensions.cs │ └── Helpers/ │ ├── MockedDbContextBuilder.cs │ ├── MockedDbContextFactory.Internal.cs │ └── NoSetUpDefaultValueProvider.cs ├── EntityFrameworkCore.Testing.Moq.Tests/ │ ├── BaseForDbContextTests.cs │ ├── BaseForDbQueryTests.cs │ ├── BaseForDbSetTests.cs │ ├── ByPropertyDbSetTests.cs │ ├── ByPropertyReadOnlyDbSetExceptionTests.cs │ ├── ByPropertyReadOnlyDbSetTests.cs │ ├── ByTypeDbSetTests.cs │ ├── ByTypeReadOnlyDbSetExceptionTests.cs │ ├── ByTypeReadOnlyDbSetTests.cs │ ├── CreateFactoryTests.cs │ ├── DbContextTestsUsingConstructorParameters.cs │ ├── DbContextTestsUsingType.cs │ ├── EntityFrameworkCore.Testing.Moq.Tests.csproj │ ├── Issue114Tests.cs │ ├── Issue117Tests.cs │ ├── Issue126Tests.cs │ ├── Issue1Tests.cs │ ├── Issue49Tests.cs │ ├── Issue4Tests.cs │ ├── Issue6Tests.cs │ └── Issue88Tests.cs ├── EntityFrameworkCore.Testing.NSubstitute/ │ ├── Create.cs │ ├── EntityFrameworkCore.Testing.NSubstitute.csproj │ ├── EntityFrameworkCore.Testing.NSubstitute.xml │ ├── Extensions/ │ │ ├── DbContextExtensions.cs │ │ ├── DbSetExtensions.Internal.cs │ │ ├── QueryProviderExtensions.Internal.cs │ │ ├── QueryProviderExtensions.cs │ │ ├── QueryableExtensions.cs │ │ ├── ReadOnlyDbSetExtensions.Internal.cs │ │ └── ReadOnlyDbSetExtensions.cs │ └── Helpers/ │ ├── MockedDbContextBuilder.cs │ ├── MockedDbContextFactory.Internal.cs │ └── NoSetUpHandler.cs └── EntityFrameworkCore.Testing.NSubstitute.Tests/ ├── BaseForDbContextTests.cs ├── BaseForDbQueryTests.cs ├── BaseForDbSetTests.cs ├── ByPropertyDbSetTests.cs ├── ByPropertyReadOnlyDbSetExceptionTests.cs ├── ByPropertyReadOnlyDbSetTests.cs ├── ByTypeDbSetTests.cs ├── ByTypeReadOnlyDbSetExceptionTests.cs ├── ByTypeReadOnlyDbSetTests.cs ├── CreateFactoryTests.cs ├── DbContextTestsUsingConstructorParameters.cs ├── DbContextTestsUsingType.cs ├── EntityFrameworkCore.Testing.NSubstitute.Tests.csproj ├── Issue114Tests.cs ├── Issue117Tests.cs ├── Issue126Tests.cs ├── Issue1Tests.cs ├── Issue49Tests.cs ├── Issue4Tests.cs ├── Issue6Tests.cs └── Issue88Tests.cs ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/workflows/continuous-integration-checks.yml ================================================ name: Continuous Integration Checks on: push: schedule: - cron: "0 9 * * 3" jobs: build-and-test: name: Build and test runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v5 - name: Setup dotnet uses: actions/setup-dotnet@v5 with: dotnet-version: 10.0.x - name: Build run: dotnet build --configuration Release # - name: List dependencies # run: dotnet list EntityFrameworkCore.Testing.sln package - name: Test 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 - name: Update dependencies run: | dotnet add src/EntityFrameworkCore.Testing.Common package Microsoft.EntityFrameworkCore.InMemory --version 10.*-* dotnet add src/EntityFrameworkCore.Testing.Common package Microsoft.EntityFrameworkCore.Relational --version 10.*-* dotnet add src/EntityFrameworkCore.Testing.Common package Microsoft.Extensions.Logging --version 10.*-* dotnet add src/EntityFrameworkCore.Testing.Common package rgvlee.Core dotnet add src/EntityFrameworkCore.Testing.Common.Tests package Microsoft.Extensions.Logging.Console --version 10.*-* dotnet add src/EntityFrameworkCore.Testing.Moq package Moq dotnet add src/EntityFrameworkCore.Testing.NSubstitute package NSubstitute # - name: List dependencies # run: dotnet list EntityFrameworkCore.Testing.sln package - name: Test with updated dependencies run: dotnet test --configuration Release /p:CollectCoverage=\"false\" /p:Exclude=\"[*.Tests]*,[rgvlee.Core.*]*\" /p:SkipAutoProps=\"false\" /p:IncludeTestAssembly=\"false\" -m:1 - name: Send coverage results to Codacy uses: codacy/codacy-coverage-reporter-action@master with: project-token: ${{ secrets.CODACY_PROJECT_TOKEN }} coverage-reports: ./CoverageResults/coverage.*opencover.xml ================================================ FILE: .github/workflows/release.yml ================================================ name: Release on: release: types: [published] jobs: build-and-test: name: Build, pack and push runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v5 - name: Setup dotnet uses: actions/setup-dotnet@v5 with: dotnet-version: 10.0.x - run: sudo apt install mono-devel - name: Setup NuGet uses: nuget/setup-nuget@v2 with: nuget-version: latest - name: Build run: dotnet build --configuration Release - name: Pack run: | nuget pack EntityFrameworkCore.Testing.Moq.nuspec -Version ${{ github.event.release.name }} -Symbols -SymbolPackageFormat snupkg nuget pack EntityFrameworkCore.Testing.NSubstitute.nuspec -Version ${{ github.event.release.name }} -Symbols -SymbolPackageFormat snupkg - name: Push run: | nuget push EntityFrameworkCore.Testing.Moq*.nupkg -Source https://api.nuget.org/v3/index.json -ApiKey ${{ secrets.NUGET_API_KEY }} nuget push EntityFrameworkCore.Testing.NSubstitute*.nupkg -Source https://api.nuget.org/v3/index.json -ApiKey ${{ secrets.NUGET_API_KEY }} ================================================ FILE: .gitignore ================================================ ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. ## ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore # User-specific files *.suo *.user *.userosscache *.sln.docstates # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs # Build results [Dd]ebug/ [Dd]ebugPublic/ [Rr]elease/ [Rr]eleases/ x64/ x86/ bld/ [Bb]in/ [Oo]bj/ [Ll]og/ # Visual Studio 2015/2017 cache/options directory .vs/ # Uncomment if you have tasks that create the project's static files in wwwroot #wwwroot/ # Visual Studio 2017 auto generated files Generated\ Files/ # MSTest test Results [Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* # NUNIT *.VisualState.xml TestResult.xml # Build Results of an ATL Project [Dd]ebugPS/ [Rr]eleasePS/ dlldata.c # Benchmark Results BenchmarkDotNet.Artifacts/ # .NET Core project.lock.json project.fragment.lock.json artifacts/ **/Properties/launchSettings.json # StyleCop StyleCopReport.xml # Files built by Visual Studio *_i.c *_p.c *_i.h *.ilk *.meta *.obj *.iobj *.pch *.pdb *.ipdb *.pgc *.pgd *.rsp *.sbr *.tlb *.tli *.tlh *.tmp *.tmp_proj *.log *.vspscc *.vssscc .builds *.pidb *.svclog *.scc # Chutzpah Test files _Chutzpah* # Visual C++ cache files ipch/ *.aps *.ncb *.opendb *.opensdf *.sdf *.cachefile *.VC.db *.VC.VC.opendb # Visual Studio profiler *.psess *.vsp *.vspx *.sap # Visual Studio Trace Files *.e2e # TFS 2012 Local Workspace $tf/ # Guidance Automation Toolkit *.gpState # ReSharper is a .NET coding add-in _ReSharper*/ *.[Rr]e[Ss]harper *.DotSettings.user # JustCode is a .NET coding add-in .JustCode # TeamCity is a build add-in _TeamCity* # DotCover is a Code Coverage Tool *.dotCover # AxoCover is a Code Coverage Tool .axoCover/* !.axoCover/settings.json # Visual Studio code coverage results *.coverage *.coveragexml # NCrunch _NCrunch_* .*crunch*.local.xml nCrunchTemp_* # MightyMoose *.mm.* AutoTest.Net/ # Web workbench (sass) .sass-cache/ # Installshield output folder [Ee]xpress/ # DocProject is a documentation generator add-in DocProject/buildhelp/ DocProject/Help/*.HxT DocProject/Help/*.HxC DocProject/Help/*.hhc DocProject/Help/*.hhk DocProject/Help/*.hhp DocProject/Help/Html2 DocProject/Help/html # Click-Once directory publish/ # Publish Web Output *.[Pp]ublish.xml *.azurePubxml # Note: Comment the next line if you want to checkin your web deploy settings, # but database connection strings (with potential passwords) will be unencrypted *.pubxml *.publishproj # Microsoft Azure Web App publish settings. Comment the next line if you want to # checkin your Azure Web App publish settings, but sensitive information contained # in these scripts will be unencrypted PublishScripts/ # NuGet Packages *.nupkg # The packages folder can be ignored because of Package Restore **/[Pp]ackages/* # except build/, which is used as an MSBuild target. !**/[Pp]ackages/build/ # Uncomment if necessary however generally it will be regenerated when needed #!**/[Pp]ackages/repositories.config # NuGet v3's project.json files produces more ignorable files *.nuget.props *.nuget.targets # Microsoft Azure Build Output csx/ *.build.csdef # Microsoft Azure Emulator ecf/ rcf/ # Windows Store app package directories and files AppPackages/ BundleArtifacts/ Package.StoreAssociation.xml _pkginfo.txt *.appx # Visual Studio cache files # files ending in .cache can be ignored *.[Cc]ache # but keep track of directories ending in .cache !*.[Cc]ache/ # Others ClientBin/ ~$* *~ *.dbmdl *.dbproj.schemaview *.jfm *.pfx *.publishsettings orleans.codegen.cs # Including strong name files can present a security risk # (https://github.com/github/gitignore/pull/2483#issue-259490424) #*.snk # Since there are multiple workflows, uncomment next line to ignore bower_components # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) #bower_components/ # RIA/Silverlight projects Generated_Code/ # Backup & report files from converting an old project file # to a newer Visual Studio version. Backup files are not needed, # because we have git ;-) _UpgradeReport_Files/ Backup*/ UpgradeLog*.XML UpgradeLog*.htm ServiceFabricBackup/ *.rptproj.bak # SQL Server files *.mdf *.ldf *.ndf # Business Intelligence projects *.rdl.data *.bim.layout *.bim_*.settings *.rptproj.rsuser # Microsoft Fakes FakesAssemblies/ # GhostDoc plugin setting file *.GhostDoc.xml # Node.js Tools for Visual Studio .ntvs_analysis.dat node_modules/ # Visual Studio 6 build log *.plg # Visual Studio 6 workspace options file *.opt # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) *.vbw # Visual Studio LightSwitch build output **/*.HTMLClient/GeneratedArtifacts **/*.DesktopClient/GeneratedArtifacts **/*.DesktopClient/ModelManifest.xml **/*.Server/GeneratedArtifacts **/*.Server/ModelManifest.xml _Pvt_Extensions # Paket dependency manager .paket/paket.exe paket-files/ # FAKE - F# Make .fake/ # JetBrains Rider .idea/ *.sln.iml # CodeRush .cr/ # Python Tools for Visual Studio (PTVS) __pycache__/ *.pyc # Cake - Uncomment if you are using it # tools/** # !tools/packages.config # Tabs Studio *.tss # Telerik's JustMock configuration file *.jmconfig # BizTalk build output *.btp.cs *.btm.cs *.odx.cs *.xsd.cs # OpenCover UI analysis results OpenCover/ # Azure Stream Analytics local run output ASALocalRun/ # MSBuild Binary and Structured Log *.binlog # NVidia Nsight GPU debugger configuration file *.nvuser # MFractors (Xamarin productivity tool) working folder .mfractor/ ================================================ FILE: EntityFrameworkCore.Testing.Moq.nuspec ================================================ EntityFrameworkCore.Testing.Moq 10.0.0 rgvlee rgvlee false LICENSE https://github.com/rgvlee/EntityFrameworkCore.Testing Adds relational support to the Microsoft EntityFrameworkCore in-memory database provider by mocking relational operations. EntityFrameworkCore.Testing v1.x = EntityFrameworkCore 2 (2.1.0+) EntityFrameworkCore.Testing v2.x = EntityFrameworkCore 3 EntityFrameworkCore.Testing v3.x = EntityFrameworkCore 5 EntityFrameworkCore.Testing v4.x = EntityFrameworkCore 6 EntityFrameworkCore.Testing v5.x = EntityFrameworkCore 7 EntityFrameworkCore.Testing v8.x = EntityFrameworkCore 8 EntityFrameworkCore.Testing v9.x = EntityFrameworkCore 9 EntityFrameworkCore.Testing v10.x = EntityFrameworkCore 10 Copyright (c) 2025 Lee Anderson EntityFrameworkCore EFCore Moq mock testing ================================================ FILE: EntityFrameworkCore.Testing.NSubstitute.nuspec ================================================ EntityFrameworkCore.Testing.NSubstitute 10.0.0 rgvlee rgvlee false LICENSE https://github.com/rgvlee/EntityFrameworkCore.Testing Adds relational support to the Microsoft EntityFrameworkCore in-memory database provider by mocking relational operations. EntityFrameworkCore.Testing v1.x = EntityFrameworkCore 2 (2.1.0+) EntityFrameworkCore.Testing v2.x = EntityFrameworkCore 3 EntityFrameworkCore.Testing v3.x = EntityFrameworkCore 5 EntityFrameworkCore.Testing v4.x = EntityFrameworkCore 6 EntityFrameworkCore.Testing v5.x = EntityFrameworkCore 7 EntityFrameworkCore.Testing v8.x = EntityFrameworkCore 8 EntityFrameworkCore.Testing v9.x = EntityFrameworkCore 9 EntityFrameworkCore.Testing v10.x = EntityFrameworkCore 10 Copyright (c) 2025 Lee Anderson EntityFrameworkCore EFCore NSubstitute nsub mock testing ================================================ FILE: EntityFrameworkCore.Testing.sln ================================================  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.3.32811.315 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F7DF11CE-7549-4808-B9BE-66CE1BD1F150}" ProjectSection(SolutionItems) = preProject .gitignore = .gitignore .github\workflows\continuous-integration-checks.yml = .github\workflows\continuous-integration-checks.yml src\EntityFrameworkCore.Testing.Common\EntityFrameworkCore.Testing.Common.xml = src\EntityFrameworkCore.Testing.Common\EntityFrameworkCore.Testing.Common.xml EntityFrameworkCore.Testing.Moq.nuspec = EntityFrameworkCore.Testing.Moq.nuspec src\EntityFrameworkCore.Testing.Moq\EntityFrameworkCore.Testing.Moq.xml = src\EntityFrameworkCore.Testing.Moq\EntityFrameworkCore.Testing.Moq.xml EntityFrameworkCore.Testing.NSubstitute.nuspec = EntityFrameworkCore.Testing.NSubstitute.nuspec src\EntityFrameworkCore.Testing.NSubstitute\EntityFrameworkCore.Testing.NSubstitute.xml = src\EntityFrameworkCore.Testing.NSubstitute\EntityFrameworkCore.Testing.NSubstitute.xml googlea6bd68d4a55b1e59.html = googlea6bd68d4a55b1e59.html LICENSE = LICENSE README.md = README.md .github\workflows\release.yml = .github\workflows\release.yml TODO.md = TODO.md EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EntityFrameworkCore.Testing.Moq", "src\EntityFrameworkCore.Testing.Moq\EntityFrameworkCore.Testing.Moq.csproj", "{3A00A558-6614-4D2C-8BC0-A74EFBB8F844}" EndProject 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}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{5B717CD0-96CD-4862-95EB-80ECCDCD1D07}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EntityFrameworkCore.Testing.Common", "src\EntityFrameworkCore.Testing.Common\EntityFrameworkCore.Testing.Common.csproj", "{F2211544-E6EA-439A-9C31-3972B48B9D5E}" EndProject 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}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EntityFrameworkCore.DefaultBehaviour.Tests", "src\EntityFrameworkCore.DefaultBehaviour.Tests\EntityFrameworkCore.DefaultBehaviour.Tests.csproj", "{9C08E46C-C902-473F-93E6-FCB89DEC8C97}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EntityFrameworkCore.Testing.NSubstitute", "src\EntityFrameworkCore.Testing.NSubstitute\EntityFrameworkCore.Testing.NSubstitute.csproj", "{A70976F0-38EA-461C-9BDE-BEE8232B048D}" EndProject 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}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {3A00A558-6614-4D2C-8BC0-A74EFBB8F844}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3A00A558-6614-4D2C-8BC0-A74EFBB8F844}.Debug|Any CPU.Build.0 = Debug|Any CPU {3A00A558-6614-4D2C-8BC0-A74EFBB8F844}.Release|Any CPU.ActiveCfg = Release|Any CPU {3A00A558-6614-4D2C-8BC0-A74EFBB8F844}.Release|Any CPU.Build.0 = Release|Any CPU {6567AA47-8E4D-4E69-8075-B8C25DC7F4A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6567AA47-8E4D-4E69-8075-B8C25DC7F4A4}.Debug|Any CPU.Build.0 = Debug|Any CPU {6567AA47-8E4D-4E69-8075-B8C25DC7F4A4}.Release|Any CPU.ActiveCfg = Release|Any CPU {6567AA47-8E4D-4E69-8075-B8C25DC7F4A4}.Release|Any CPU.Build.0 = Release|Any CPU {F2211544-E6EA-439A-9C31-3972B48B9D5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F2211544-E6EA-439A-9C31-3972B48B9D5E}.Debug|Any CPU.Build.0 = Debug|Any CPU {F2211544-E6EA-439A-9C31-3972B48B9D5E}.Release|Any CPU.ActiveCfg = Release|Any CPU {F2211544-E6EA-439A-9C31-3972B48B9D5E}.Release|Any CPU.Build.0 = Release|Any CPU {4B97C16B-E27D-4900-A535-6D5AC116B893}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4B97C16B-E27D-4900-A535-6D5AC116B893}.Debug|Any CPU.Build.0 = Debug|Any CPU {4B97C16B-E27D-4900-A535-6D5AC116B893}.Release|Any CPU.ActiveCfg = Release|Any CPU {4B97C16B-E27D-4900-A535-6D5AC116B893}.Release|Any CPU.Build.0 = Release|Any CPU {9C08E46C-C902-473F-93E6-FCB89DEC8C97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9C08E46C-C902-473F-93E6-FCB89DEC8C97}.Debug|Any CPU.Build.0 = Debug|Any CPU {9C08E46C-C902-473F-93E6-FCB89DEC8C97}.Release|Any CPU.ActiveCfg = Release|Any CPU {9C08E46C-C902-473F-93E6-FCB89DEC8C97}.Release|Any CPU.Build.0 = Release|Any CPU {A70976F0-38EA-461C-9BDE-BEE8232B048D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A70976F0-38EA-461C-9BDE-BEE8232B048D}.Debug|Any CPU.Build.0 = Debug|Any CPU {A70976F0-38EA-461C-9BDE-BEE8232B048D}.Release|Any CPU.ActiveCfg = Release|Any CPU {A70976F0-38EA-461C-9BDE-BEE8232B048D}.Release|Any CPU.Build.0 = Release|Any CPU {2F67273D-B7B8-49A5-9A91-E37CBC10F563}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2F67273D-B7B8-49A5-9A91-E37CBC10F563}.Debug|Any CPU.Build.0 = Debug|Any CPU {2F67273D-B7B8-49A5-9A91-E37CBC10F563}.Release|Any CPU.ActiveCfg = Release|Any CPU {2F67273D-B7B8-49A5-9A91-E37CBC10F563}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {6567AA47-8E4D-4E69-8075-B8C25DC7F4A4} = {5B717CD0-96CD-4862-95EB-80ECCDCD1D07} {4B97C16B-E27D-4900-A535-6D5AC116B893} = {5B717CD0-96CD-4862-95EB-80ECCDCD1D07} {9C08E46C-C902-473F-93E6-FCB89DEC8C97} = {5B717CD0-96CD-4862-95EB-80ECCDCD1D07} {2F67273D-B7B8-49A5-9A91-E37CBC10F563} = {5B717CD0-96CD-4862-95EB-80ECCDCD1D07} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {0E585345-42EF-438B-8212-2C328D36D9AD} EndGlobalSection EndGlobal ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2025 Lee Anderson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # EntityFrameworkCore.Testing [![Codacy Badge](https://app.codacy.com/project/badge/Grade/6d641ce391264f45b99acee8694a88d6?branch=10.x)](https://www.codacy.com/manual/rgvlee/EntityFrameworkCore.Testing?utm_source=github.com&utm_medium=referral&utm_content=rgvlee/EntityFrameworkCore.Testing&utm_campaign=Badge_Grade) [![Codacy Badge](https://app.codacy.com/project/badge/Coverage/6d641ce391264f45b99acee8694a88d6?branch=10.x)](https://www.codacy.com/manual/rgvlee/EntityFrameworkCore.Testing?utm_source=github.com&utm_medium=referral&utm_content=rgvlee/EntityFrameworkCore.Testing&utm_campaign=Badge_Coverage) ## Overview EntityFrameworkCore.Testing adds relational support to the Microsoft EntityFrameworkCore in-memory database provider by mocking relational operations. It's easy to use (usually just a single line of code) with implementations for both Moq and NSubstitute. The aim of this library is to allow you use the in-memory database provider in unit tests where the SUT invokes a relational operation. It'll allow you to specify expected results for these relational operations. It does not test your relational operations. [Microsoft does not recommend mocking a db context](https://docs.microsoft.com/en-us/ef/core/testing/#unit-testing) and EntityFrameworkCore.Testing follows this advice by sending operations supported by the in-memory database provider to the in-memory database provider. ### EntityFrameworkCore 10 - [Source](https://github.com/rgvlee/EntityFrameworkCore.Testing/tree/10.x) - [EntityFrameworkCore.Testing.Moq - NuGet](https://www.nuget.org/packages/EntityFrameworkCore.Testing.Moq/10.0.0) - [EntityFrameworkCore.Testing.NSubstitute - NuGet](https://www.nuget.org/packages/EntityFrameworkCore.Testing.NSubstitute/10.0.0) ### EntityFrameworkCore 9 - [Source](https://github.com/rgvlee/EntityFrameworkCore.Testing/tree/9.x) - [EntityFrameworkCore.Testing.Moq - NuGet](https://www.nuget.org/packages/EntityFrameworkCore.Testing.Moq/9.0.2) - [EntityFrameworkCore.Testing.NSubstitute - NuGet](https://www.nuget.org/packages/EntityFrameworkCore.Testing.NSubstitute/9.0.2) ### EntityFrameworkCore 8 - [Source](https://github.com/rgvlee/EntityFrameworkCore.Testing/tree/8.x) - [EntityFrameworkCore.Testing.Moq - NuGet](https://www.nuget.org/packages/EntityFrameworkCore.Testing.Moq/8.1.2) - [EntityFrameworkCore.Testing.NSubstitute - NuGet](https://www.nuget.org/packages/EntityFrameworkCore.Testing.NSubstitute/8.1.2) ### EntityFrameworkCore 7 - [Source](https://github.com/rgvlee/EntityFrameworkCore.Testing/tree/5.x) - [EntityFrameworkCore.Testing.Moq - NuGet](https://www.nuget.org/packages/EntityFrameworkCore.Testing.Moq/5.0.0) - [EntityFrameworkCore.Testing.NSubstitute - NuGet](https://www.nuget.org/packages/EntityFrameworkCore.Testing.NSubstitute/5.0.0) ### EntityFrameworkCore 6 - [Source](https://github.com/rgvlee/EntityFrameworkCore.Testing/tree/4.x) - [EntityFrameworkCore.Testing.Moq - NuGet](https://www.nuget.org/packages/EntityFrameworkCore.Testing.Moq/4.0.2) - [EntityFrameworkCore.Testing.NSubstitute - NuGet](https://www.nuget.org/packages/EntityFrameworkCore.Testing.NSubstitute/4.0.2) ### EntityFrameworkCore 5 - [Source](https://github.com/rgvlee/EntityFrameworkCore.Testing/tree/3.x) - [EntityFrameworkCore.Testing.Moq - NuGet](https://www.nuget.org/packages/EntityFrameworkCore.Testing.Moq/3.0.5) - [EntityFrameworkCore.Testing.NSubstitute - NuGet](https://www.nuget.org/packages/EntityFrameworkCore.Testing.NSubstitute/3.0.5) ### EntityFrameworkCore 3 - [Source](https://github.com/rgvlee/EntityFrameworkCore.Testing/tree/2.x) - [EntityFrameworkCore.Testing.Moq - NuGet](https://www.nuget.org/packages/EntityFrameworkCore.Testing.Moq/2.4.5) - [EntityFrameworkCore.Testing.NSubstitute - NuGet](https://www.nuget.org/packages/EntityFrameworkCore.Testing.NSubstitute/2.4.5) ### EntityFrameworkCore 2 (2.1.0+) - [Source](https://github.com/rgvlee/EntityFrameworkCore.Testing/tree/1.x) - [EntityFrameworkCore.Testing.Moq - NuGet](https://www.nuget.org/packages/EntityFrameworkCore.Testing.Moq/1.3.5) - [EntityFrameworkCore.Testing.NSubstitute - NuGet](https://www.nuget.org/packages/EntityFrameworkCore.Testing.NSubstitute/1.3.5) ## Prerequisites ### An accessible constructor Your db context must have an accessible constructor. ### Virtual sets/queries Your db context set/query properties must be overridable: ```c# public virtual DbSet TestEntities { get; set; } ``` ## Creating a mocked DbContext If your db context has an accessible constructor with a single `DbContextOptions` or `DbContextOptions` parameter, creating a mocked db context is as easy as: ```c# var mockedDbContext = Create.MockedDbContextFor(); ``` Any accessible constructor can be used provided it has a `DbContextOptions` or `DbContextOptions` parameter: ```c# var mockedLogger = Mock.Of>(); var dbContextOptions = new DbContextOptionsBuilder().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options; var mockedDbContext = Create.MockedDbContextFor(mockedLogger, dbContextOptions); ``` Both of the above examples automatically create and use a Microsoft in-memory provider instance for the EntityFrameworkCore provider. If you want more control e.g., to specify the EntityFrameworkCore provider instance, use the builder: ```c# var options = new DbContextOptionsBuilder().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options; var dbContextToMock = new TestDbContext(options); var mockedDbContext = new MockedDbContextBuilder().UseDbContext(dbContextToMock).UseConstructorWithParameters(options).MockedDbContext; ``` There is no requirement to use the Microsoft in-memory provider. The following example uses the SQLite in-memory provider for a db context with a parameterless constructor: ```c# using (var connection = new SqliteConnection("Filename=:memory:")) { connection.Open(); var testEntity = _fixture.Create(); var dbContextToMock = new TestDbContext(new DbContextOptionsBuilder().UseSqlite(connection).Options); dbContextToMock.Database.EnsureCreated(); var mockedDbContext = new MockedDbContextBuilder().UseDbContext(dbContextToMock).MockedDbContext; mockedDbContext.Set().Add(testEntity); mockedDbContext.SaveChanges(); Assert.Multiple(() => { Assert.AreNotEqual(default(Guid), testEntity.Id); Assert.DoesNotThrow(() => mockedDbContext.Set().Single()); Assert.AreEqual(testEntity, mockedDbContext.Find(testEntity.Id)); }); } ``` ## Usage Start by creating a mocked db context and, if the SUT requires, populate it as if you were using the real thing: ```c# var testEntity = _fixture.Create(); var mockedDbContext = Create.MockedDbContextFor(); mockedDbContext.Set().Add(testEntity); mockedDbContext.SaveChanges(); Assert.Multiple(() => { Assert.AreNotEqual(default(Guid), testEntity.Id); Assert.DoesNotThrow(() => mockedDbContext.Set().Single()); Assert.AreEqual(testEntity, mockedDbContext.Find(testEntity.Id)); }); ``` The Moq implementation of `Create.MockedDbContextFor()` returns the mocked db context. If you need the mock itself (e.g., to verify an invocation) use `Mock.Get(mockedDbSet)`: ```c# var mockedDbContext = Create.MockedDbContextFor(); mockedDbContext.Set().AddRange(_fixture.CreateMany().ToList()); mockedDbContext.SaveChanges(); Assert.Multiple(() => { var dbContextMock = Mock.Get(mockedDbContext); dbContextMock.Verify(m => m.SaveChanges(), Times.Once); }); ``` ### FromSql Use `AddFromSqlResult` to add a from SQL result to the mock. The following will return `expectedResult` for any `FromSql` invocation: ```c# var expectedResult = _fixture.CreateMany().ToList(); var mockedDbContext = Create.MockedDbContextFor(); mockedDbContext.Set().AddFromSqlRawResult(expectedResult); var actualResult = mockedDbContext.Set().FromSqlRaw("[dbo].[USP_StoredProcedureWithNoParameters]").ToList(); Assert.Multiple(() => { Assert.IsNotNull(actualResult); Assert.IsTrue(actualResult.Any()); CollectionAssert.AreEquivalent(expectedResult, actualResult); }); ``` The following will return `expectedResult` if the `FromSql` SQL query text contains `usp_StoredProcedureWithParameters` and a `@Parameter2` SQL parameter with a value of `Value2` has been provided: ```c# var expectedResult = _fixture.CreateMany().ToList(); var sqlParameters = new List { new SqlParameter("@Parameter2", "Value2") }; var mockedDbContext = Create.MockedDbContextFor(); mockedDbContext.Set().AddFromSqlRawResult("usp_StoredProcedureWithParameters", sqlParameters, expectedResult); var actualResult = mockedDbContext.Set() .FromSqlRaw("[dbo].[USP_StoredProcedureWithParameters] @Parameter1 @Parameter2", new SqlParameter("@parameter1", "Value1"), new SqlParameter("@parameter2", "value2")) .ToList(); Assert.Multiple(() => { Assert.IsNotNull(actualResult); Assert.IsTrue(actualResult.Any()); CollectionAssert.AreEquivalent(expectedResult, actualResult); }); ``` SQL query text matching supports partial, case insensitive matches. Individual parameter name and value matching is also case insensitive. Case insensitive interpolated strings are also supported: ```c# var expectedResult = _fixture.CreateMany().ToList(); var parameter1 = _fixture.Create(); var parameter2 = _fixture.Create(); var mockedDbContext = Create.MockedDbContextFor(); mockedDbContext.Set().AddFromSqlInterpolatedResult($"usp_StoredProcedureWithParameters {parameter1}, {parameter2.ToUpper()}", expectedResult); var actualResult = mockedDbContext.Set().FromSqlInterpolated($"USP_StoredProcedureWithParameters {parameter1}, {parameter2.ToLower()}").ToList(); Assert.Multiple(() => { Assert.IsNotNull(actualResult); Assert.IsTrue(actualResult.Any()); CollectionAssert.AreEquivalent(expectedResult, actualResult); }); ``` ### FromSqlRaw/FromSqlInterpolated (EntityFrameworkCore 3.\*) Use `AddFromSqlRawResult` and `AddFromSqlInterpolatedResult` to add results for `FromSqlRaw` and `FromSqlInterpolated` invocations. Refer to the FromSql section above for usage. ### Queries Use `AddToReadOnlySource`, `AddRangeToReadOnlySource` and `ClearReadOnlySource` to manage a query source. ```c# var expectedResult = _fixture.CreateMany().ToList(); var mockedDbContext = Create.MockedDbContextFor(); mockedDbContext.Set().AddRangeToReadOnlySource(expectedResult); Assert.Multiple(() => { CollectionAssert.AreEquivalent(expectedResult, mockedDbContext.Set().ToList()); CollectionAssert.AreEquivalent(mockedDbContext.Set().ToList(), mockedDbContext.TestReadOnlyEntities.ToList()); }); ``` Specifying a from SQL result for a query is exactly the same as for a set. ### Keyless Sets (EntityFrameworkCore 3.\*) Refer to the Queries section above for usage. ### ExecuteSqlCommand Adding an execute SQL command result is similar to adding a from SQL result with the main difference being the return type. `ExecuteSqlCommand` returns an `int` (the number of rows affected by executing the SQL command text). ```c# var commandText = "usp_StoredProcedureWithNoParameters"; var expectedResult = 1; var mockedDbContext = Create.MockedDbContextFor(); mockedDbContext.AddExecuteSqlRawResult(commandText, new List(), expectedResult); var result = mockedDbContext.Database.ExecuteSqlRaw("USP_StoredProcedureWithNoParameters"); Assert.AreEqual(expectedResult, result); ``` All of the overloads have an optional `Action>` parameter which allows you to perform operations post invocation. The following provides a basic example where invoking `ExecuteSqlCommand` deletes a specified number of rows from a set: ```c# //Arrange var mockedDbContext = Create.MockedDbContextFor(); var itemsToCreate = 100; mockedDbContext.Set().AddRange(_fixture.CreateMany(itemsToCreate).ToList()); mockedDbContext.SaveChanges(); var numberOfRowsToDelete = itemsToCreate / 2; var rowsToDelete = mockedDbContext.Set().Take(numberOfRowsToDelete).ToList(); var remainingRows = mockedDbContext.Set().Skip(numberOfRowsToDelete).ToList(); mockedDbContext.AddExecuteSqlRawResult("usp_MyStoredProc", numberOfRowsToDelete, (providedSql, providedParameters) => { mockedDbContext.Set().RemoveRange(rowsToDelete); mockedDbContext.SaveChanges(); }); //Act var actualResult = mockedDbContext.Database.ExecuteSqlRaw($"usp_MyStoredProc {numberOfRowsToDelete}"); //Assert Assert.Multiple(() => { Assert.That(actualResult, Is.EqualTo(numberOfRowsToDelete)); Assert.That(mockedDbContext.Set().Count(), Is.EqualTo(itemsToCreate - numberOfRowsToDelete)); Assert.That(mockedDbContext.Set().ToList(), Is.EquivalentTo(remainingRows)); }); ``` ### ExecuteSqlRaw/ExecuteSqlInterpolated (EntityFrameworkCore 3.\*) Use `AddExecuteSqlRawResult` and `AddExecuteSqlInterpolatedResult` to add results for `ExecuteSqlRaw` and `ExecuteSqlInterpolated` invocations. Refer to the ExecuteSqlCommand section above for usage. ### Async and LINQ queryable operations Whenever you add a from SQL or execute SQL command result, EntityFrameworkCore.Testing sets up both the sync and async methods. It also automatically provides support for all sync and async LINQ queryable operations that are not supported by the Microsoft in-memory provider. ### Asserting mock invocations The db context and each set, query and their respective query providers are separate mocks. The following Moq example asserts that the `DbContext.SaveChanges` and `DbSet.AddRange` methods were both invoked once. ```c# var mockedDbContext = Create.MockedDbContextFor(); mockedDbContext.Set().AddRange(_fixture.CreateMany().ToList()); mockedDbContext.SaveChanges(); var dbContextMock = Mock.Get(mockedDbContext); dbContextMock.Verify(m => m.SaveChanges(), Times.Once); var byTypeDbSetMock = Mock.Get(mockedDbContext.Set()); byTypeDbSetMock.Verify(m => m.AddRange(It.IsAny>()), Times.Once); var byPropertyDbSetMock = Mock.Get(mockedDbContext.TestEntities); byPropertyDbSetMock.Verify(m => m.AddRange(It.IsAny>()), Times.Once); ``` ================================================ FILE: TODO.md ================================================ # TODO - Add tests for untested functionality - Remove repeated set up code - Unify test structures to assist with cross project comparisons - Add default behaviour tests for SQL Server provider ================================================ FILE: googlea6bd68d4a55b1e59.html ================================================ google-site-verification: googlea6bd68d4a55b1e59.html ================================================ FILE: src/EntityFrameworkCore.DefaultBehaviour.Tests/ByTypeDbSetTests.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using AutoFixture; using EntityFrameworkCore.Testing.Common.Tests; using FluentAssertions; using Microsoft.EntityFrameworkCore; using NUnit.Framework; using static FluentAssertions.FluentActions; namespace EntityFrameworkCore.DefaultBehaviour.Tests; public class ByTypeDbSetTests : BaseForQueryableTests { protected TestDbContext DbContext; protected DbSet DbSet => DbContext.Set(); protected override IQueryable Queryable => DbSet; [SetUp] public override void SetUp() { base.SetUp(); DbContext = new TestDbContext(new DbContextOptionsBuilder().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options); } protected override void SeedQueryableSource() { var itemsToAdd = Fixture.Build().With(p => p.CreatedAt, DateTime.Today).With(p => p.LastModifiedAt, DateTime.Today).CreateMany().ToList(); DbContext.Set().AddRange(itemsToAdd); DbContext.SaveChanges(); ItemsAddedToQueryableSource = itemsToAdd; } [Test] public virtual async Task AsAsyncEnumerable_ReturnsAsyncEnumerable() { var expectedResult = Fixture.Create(); DbSet.Add(expectedResult); DbContext.SaveChanges(); var asyncEnumerable = DbSet.AsAsyncEnumerable(); var actualResults = new List(); await foreach (var item in asyncEnumerable) actualResults.Add(item); Assert.Multiple(() => { Assert.That(actualResults.Single(), Is.EqualTo(expectedResult)); Assert.That(actualResults.Single(), Is.EqualTo(expectedResult)); }); } [Test] public virtual void AsQueryable_ReturnsQueryable() { var expectedResult = Fixture.Create(); DbSet.Add(expectedResult); DbContext.SaveChanges(); var queryable = DbSet.AsQueryable(); Assert.Multiple(() => { Assert.That(queryable.Single(), Is.EqualTo(expectedResult)); Assert.That(queryable.Single(), Is.EqualTo(expectedResult)); }); } [Test] public virtual void FromSqlInterpolated_ThrowsException() { Invoking(() => DbSet.FromSqlInterpolated($"sp_NoParams").ToList()).Should().ThrowExactly(); } [Test] public virtual void FromSqlRaw_ThrowsException() { Invoking(() => DbSet.FromSqlRaw("sp_NoParams").ToList()).Should().ThrowExactly(); } } ================================================ FILE: src/EntityFrameworkCore.DefaultBehaviour.Tests/ByTypeReadOnlyDbSetExceptionTests.cs ================================================ using System; using EntityFrameworkCore.Testing.Common.Tests; using Microsoft.EntityFrameworkCore; using NUnit.Framework; namespace EntityFrameworkCore.DefaultBehaviour.Tests { public class ReadOnlyDbSetExceptionTests : ReadOnlyDbSetExceptionTests { protected TestDbContext DbContext; protected override DbSet DbSet => DbContext.Set(); [SetUp] public override void SetUp() { base.SetUp(); DbContext = new TestDbContext(new DbContextOptionsBuilder().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options); } } } ================================================ FILE: src/EntityFrameworkCore.DefaultBehaviour.Tests/ByTypeReadOnlyDbSetTests.cs ================================================ using System; using System.ComponentModel; using EntityFrameworkCore.Testing.Common.Tests; using Microsoft.EntityFrameworkCore; using NUnit.Framework; namespace EntityFrameworkCore.DefaultBehaviour.Tests { public class ByTypeReadOnlyDbSetTests : BaseForTests { protected TestDbContext DbContext; protected DbSet DbSet => DbContext.Set(); [SetUp] public override void SetUp() { base.SetUp(); DbContext = new TestDbContext(new DbContextOptionsBuilder().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options); } [Test] public virtual void AsAsyncEnumerable_ReturnsAsyncEnumerable() { var asyncEnumerable = DbSet.AsAsyncEnumerable(); Assert.That(asyncEnumerable, Is.Not.Null); } [Test] public virtual void AsQueryable_ReturnsQueryable() { var queryable = DbSet.AsQueryable(); Assert.That(queryable, Is.Not.Null); } [Test] public void ContainsListCollection_ReturnsFalse() { var containsListCollection = ((IListSource) DbSet).ContainsListCollection; Assert.That(containsListCollection, Is.False); } } } ================================================ FILE: src/EntityFrameworkCore.DefaultBehaviour.Tests/DbContextTests.cs ================================================ using System; using System.Linq; using EntityFrameworkCore.Testing.Common; using EntityFrameworkCore.Testing.Common.Tests; using Microsoft.EntityFrameworkCore; using NUnit.Framework; namespace EntityFrameworkCore.DefaultBehaviour.Tests { public class DbContextTests : BaseForTests { protected TestDbContext DbContext; [SetUp] public override void SetUp() { base.SetUp(); DbContext = new TestDbContext(new DbContextOptionsBuilder().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options); } [Test] public virtual void ExecuteSqlInterpolated_ThrowsException() { Assert.Throws(() => { var actualResult = DbContext.Database.ExecuteSqlInterpolated($"sp_NoParams"); }); } [Test] public virtual void ExecuteSqlRaw_ThrowsException() { Assert.Throws(() => { var actualResult = DbContext.Database.ExecuteSqlRaw("sp_NoParams"); }); } [Test] public virtual void Set_TypeNotIncludedInModel_ThrowsException() { Assert.Multiple(() => { var ex = Assert.Throws(() => DbContext.Set().ToList()); Assert.That(ex.Message, Is.EqualTo(string.Format(ExceptionMessages.CannotCreateDbSetTypeNotIncludedInModel, nameof(NotRegisteredEntity)))); }); } [Test] public virtual void SetCommandTimeout_ValidTimeout_ThrowsException() { Assert.Throws(() => { DbContext.Database.SetCommandTimeout(60); }); } [Test] public virtual void GetCommandTimeout_ThrowsException() { Assert.Throws(() => { DbContext.Database.GetCommandTimeout(); }); } } } ================================================ FILE: src/EntityFrameworkCore.DefaultBehaviour.Tests/EntityFrameworkCore.DefaultBehaviour.Tests.csproj ================================================ net10.0 false NU1605 true NU1605 all runtime; build; native; contentfiles; analyzers; buildtransitive ================================================ FILE: src/EntityFrameworkCore.DefaultBehaviour.Tests/Issue114Tests.cs ================================================ using System; using Microsoft.EntityFrameworkCore; namespace EntityFrameworkCore.DefaultBehaviour.Tests { public class Issue114Tests : Testing.Common.Tests.Issue114Tests { protected override TestDbContext MockedDbContextFactory() { return new TestDbContext(new DbContextOptionsBuilder().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options); } } } ================================================ FILE: src/EntityFrameworkCore.DefaultBehaviour.Tests/Issue117Tests.cs ================================================ using System; using Microsoft.EntityFrameworkCore; namespace EntityFrameworkCore.DefaultBehaviour.Tests { public class Issue117Tests : Testing.Common.Tests.Issue117Tests { protected override TestDbContext MockedDbContextFactory() { return new TestDbContext(new DbContextOptionsBuilder().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options); } } } ================================================ FILE: src/EntityFrameworkCore.DefaultBehaviour.Tests/Issue49Tests.cs ================================================ using System; using EntityFrameworkCore.Testing.Common.Tests; using Microsoft.EntityFrameworkCore; using NUnit.Framework; namespace EntityFrameworkCore.DefaultBehaviour.Tests { public class Issue49Tests : Issue49Tests { [SetUp] public override void SetUp() { base.SetUp(); DbContext = new TestDbContext(new DbContextOptionsBuilder().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options); } } } ================================================ FILE: src/EntityFrameworkCore.DefaultBehaviour.Tests/Issue88Tests.cs ================================================ using System; using EntityFrameworkCore.Testing.Common.Tests; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Diagnostics; using NUnit.Framework; namespace EntityFrameworkCore.DefaultBehaviour.Tests { public class Issue88Tests : Issue88Tests { [SetUp] public override void SetUp() { base.SetUp(); var options = new DbContextOptionsBuilder() .UseInMemoryDatabase(Guid.NewGuid().ToString()) .ConfigureWarnings(x => x.Ignore(InMemoryEventId.TransactionIgnoredWarning)) .Options; DbContextFactory = () => new TestDbContext(options); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Common/AsyncEnumerable.cs ================================================ using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Threading; using Microsoft.EntityFrameworkCore.Query; namespace EntityFrameworkCore.Testing.Common { public class AsyncEnumerable : IAsyncEnumerable, IOrderedQueryable { private readonly IQueryable _source; public AsyncEnumerable(IEnumerable enumerable) { _source = enumerable.AsQueryable(); Provider = new AsyncQueryProvider(_source); Expression = _source.Expression; } public AsyncEnumerable(IEnumerable enumerable, QueryRootExpression expression) : this(enumerable) { Expression = expression; } public IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = new()) { return new AsyncEnumerator(_source); } IEnumerator IEnumerable.GetEnumerator() { return _source.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return _source.GetEnumerator(); } public Type ElementType => typeof(T); public Expression Expression { get; } public IQueryProvider Provider { get; } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Common/AsyncEnumerator.cs ================================================ using System.Collections.Generic; using System.Threading.Tasks; namespace EntityFrameworkCore.Testing.Common { public class AsyncEnumerator : IAsyncEnumerator { private readonly IEnumerator _enumerator; public AsyncEnumerator(IEnumerable enumerable) { _enumerator = enumerable.GetEnumerator(); } public ValueTask DisposeAsync() { return new(); } public ValueTask MoveNextAsync() { return new(_enumerator.MoveNext()); } public T Current => _enumerator.Current; } } ================================================ FILE: src/EntityFrameworkCore.Testing.Common/AsyncQueryProvider.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Threading; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.Extensions.Logging; using rgvlee.Core.Common.Helpers; using ProjectExpressionHelper = EntityFrameworkCore.Testing.Common.Helpers.ExpressionHelper; namespace EntityFrameworkCore.Testing.Common { /// public class AsyncQueryProvider : IAsyncQueryProvider { private static readonly ILogger Logger = LoggingHelper.CreateLogger>(); public AsyncQueryProvider(IEnumerable enumerable) { Source = enumerable.AsQueryable(); } /// /// The query provider source. /// public IQueryable Source { get; set; } /// /// In this implementation it is just a wrapper for public virtual IQueryable CreateQuery(Expression expression) { Logger.LogDebug("CreateQuery: invoked"); //Handles cases where we are projecting to another type if (expression is MethodCallExpression mce) { var returnType = mce.Method.ReturnType; if (returnType.GetGenericTypeDefinition() != typeof(IQueryable<>)) { throw new InvalidOperationException($"Expected IQueryable<>; actual {returnType.FullName}"); } var createQueryMethod = typeof(IQueryProvider).GetMethods().Single(x => x.Name.Equals(nameof(IQueryProvider.CreateQuery)) && x.IsGenericMethod); var createQueryResult = createQueryMethod.MakeGenericMethod(returnType.GetGenericArguments().Single()).Invoke(this, new[] { expression }); return (IQueryable) Activator.CreateInstance(typeof(AsyncEnumerable<>).GetGenericTypeDefinition().MakeGenericType(returnType.GetGenericArguments().Single()), createQueryResult); } return CreateQuery(expression); } /// public virtual IQueryable CreateQuery(Expression expression) { Logger.LogDebug("CreateQuery: invoked"); if (expression is FromSqlQueryRootExpression) { Logger.LogDebug("CreateQuery: catch all exception invoked"); throw new NotSupportedException(); } ProjectExpressionHelper.ThrowIfExpressionIsNotSupported(expression); return new AsyncEnumerable(Source.Provider.CreateQuery(EnsureExpressionCanBeResolvedBySourceProvider(expression))); } /// public virtual object Execute(Expression expression) { Logger.LogDebug("Execute: invoked"); ProjectExpressionHelper.ThrowIfExpressionIsNotSupported(expression); return Source.Provider.Execute(EnsureExpressionCanBeResolvedBySourceProvider(expression)); } /// public virtual TResult Execute(Expression expression) { Logger.LogDebug("Execute: invoked"); ProjectExpressionHelper.ThrowIfExpressionIsNotSupported(expression); return Source.Provider.Execute(EnsureExpressionCanBeResolvedBySourceProvider(expression)); } /// public virtual TResult ExecuteAsync(Expression expression, CancellationToken cancellationToken) { //TResult is a Task. The provider requires T. return (TResult) typeof(AsyncQueryProvider).GetMethod(nameof(WrapExecuteAsync), BindingFlags.Instance | BindingFlags.NonPublic) .MakeGenericMethod(typeof(TResult).GetGenericArguments()) .Invoke(this, new object[] { expression, cancellationToken }); } private Task WrapExecuteAsync(Expression expression, CancellationToken cancellationToken) { return Task.FromResult(Execute(expression)); } private Expression EnsureExpressionCanBeResolvedBySourceProvider(Expression expression) { Logger.LogDebug("EnsureExpressionCanBeResolvedBySourceProvider: invoked"); if (expression is MethodCallExpression mce && mce.Arguments[0] is Microsoft.EntityFrameworkCore.Query.QueryRootExpression) { for (var i = 0; i < mce.Arguments.Count; i++) { Logger.LogDebug("argument[{i}]: {argument}", i, mce.Arguments[i].ToString()); } //This ensures that Source provider will always be able to resolve the expression var arguments = new List(); arguments.Add(Source.Expression); arguments.AddRange(mce.Arguments.Skip(1)); Logger.LogDebug("sourceExpression: {sourceExpression}", Source.Expression.ToString()); for (var i = 0; i < mce.Arguments.Count; i++) { Logger.LogDebug("argument[{i}]: {argument}", i, mce.Arguments[i].ToString()); } return Expression.Call(mce.Method, arguments); } return expression; } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Common/EntityFrameworkCore.Testing.Common.csproj ================================================ net10.0 rgvlee EntityFrameworkCore.Testing.Common.xml NU1605 EntityFrameworkCore.Testing.Common.xml true NU1605 True True ExceptionMessages.resx PublicResXFileCodeGenerator ExceptionMessages.Designer.cs ================================================ FILE: src/EntityFrameworkCore.Testing.Common/EntityFrameworkCore.Testing.Common.xml ================================================ EntityFrameworkCore.Testing.Common The query provider source. In this implementation it is just a wrapper for A strongly-typed resource class, for looking up localized strings, etc. Returns the cached ResourceManager instance used by this class. Overrides the current thread's CurrentUICulture property for all resource lookups using this strongly typed resource class. 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.. Looks up a localized string similar to Unable to find a suitable constructor. TDbContext must have a parameterless or DbContextOptions/DbContextOptions<TDbContext> constructor.. The mocked db context builder. The db context type. The create factory options. The mocked db context. The parameters that will be used to create the mocked db context and, if one is not provided, the in-memory context that the mocked db context will use for in-memory provider supported operations. The constructor parameters. The mocked db context builder. The db context instance that the mocked db context will use for in-memory provider supported operations. The base mocked db context factory. The db context type. The logger instance. The parameters that will be used to create the mocked db context and, if one is not provided, the in-memory context that the mocked db context will use for in-memory provider supported operations. The db context instance that the mocked db context will use for in-memory provider supported operations. Constructor. The mocked db context factory options. Creates and sets up a mocked db context. A mocked db context. A helper for expressions. Creates a property expression for the specified property. The expression parameter. The expression property. The property info of the property to create the expression for. A property expression for the specified property. The mocked db context builder. The db context type. The mocked db context. The parameters that will be used to create the mocked db context and, if one is not provided, the in-memory context that the mocked db context will use for in-memory provider supported operations. The constructor parameters. The mocked db context builder. The db context instance that the mocked db context will use for in-memory provider supported operations. The mocked db context factory options. The db context type. The db context instance that the mocked db context will use for in-memory provider supported operations. The parameters that will be used to create the mocked db context and, if one is not provided, the in-memory context that the mocked db context will use for in-memory provider supported operations. A helper for parameter matching. Determines whether the invocation parameters match the set up parameters. The set up parameters. The invocation parameters. true the invocation parameters are a partial or full match of the set up parameters. If the parameters are DbParameters, parameter name and value are compared. Parameter name matching is case insensitive. If the value is a string, the matching is case insensitive. For everything else an exact match is required. Converts a sequence of invocation parameters to a string of parameter names and values. The invocation parameters. A string of parameter names and values. ================================================ FILE: src/EntityFrameworkCore.Testing.Common/ExceptionMessages.Designer.cs ================================================ //------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ namespace EntityFrameworkCore.Testing.Common { using System; /// /// A strongly-typed resource class, for looking up localized strings, etc. /// // This class was auto-generated by the StronglyTypedResourceBuilder // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] public class ExceptionMessages { private static global::System.Resources.ResourceManager resourceMan; private static global::System.Globalization.CultureInfo resourceCulture; [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal ExceptionMessages() { } /// /// Returns the cached ResourceManager instance used by this class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] public static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("EntityFrameworkCore.Testing.Common.ExceptionMessages", typeof(ExceptionMessages).Assembly); resourceMan = temp; } return resourceMan; } } /// /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] public static global::System.Globalization.CultureInfo Culture { get { return resourceCulture; } set { resourceCulture = value; } } /// /// 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.. /// public static string CannotCreateDbSetTypeNotIncludedInModel { get { return ResourceManager.GetString("CannotCreateDbSetTypeNotIncludedInModel", resourceCulture); } } /// /// Looks up a localized string similar to Unable to find a suitable constructor. TDbContext must have a parameterless or DbContextOptions/DbContextOptions<TDbContext> constructor.. /// public static string UnableToFindSuitableDbContextConstructor { get { return ResourceManager.GetString("UnableToFindSuitableDbContextConstructor", resourceCulture); } } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Common/ExceptionMessages.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 Cannot create a DbSet for '{0}' because this type is not included in the model for the context. Unable to find a suitable constructor. TDbContext must have a parameterless or DbContextOptions/DbContextOptions<TDbContext> constructor. ================================================ FILE: src/EntityFrameworkCore.Testing.Common/Helpers/BaseMockedDbContextBuilder.cs ================================================ using Microsoft.EntityFrameworkCore; using rgvlee.Core.Common.Helpers; namespace EntityFrameworkCore.Testing.Common.Helpers { /// /// The mocked db context builder. /// /// The db context type. public abstract class BaseMockedDbContextBuilder : IMockedDbContextBuilder where TDbContext : DbContext { /// /// The create factory options. /// protected readonly MockedDbContextFactoryOptions Options = new(); /// /// The mocked db context. /// public abstract TDbContext MockedDbContext { get; } /// /// The parameters that will be used to create the mocked db context and, if one is not provided, /// the in-memory context that the mocked db context will use for in-memory provider supported operations. /// /// /// The constructor parameters. /// /// The mocked db context builder. public IMockedDbContextBuilder UseConstructorWithParameters(params object[] constructorParameters) { EnsureArgument.IsNotEmpty(constructorParameters, nameof(constructorParameters)); Options.ConstructorParameters = constructorParameters; return this; } /// /// The db context instance that the mocked db context will use for in-memory provider supported operations. /// public IMockedDbContextBuilder UseDbContext(TDbContext dbContext) { EnsureArgument.IsNotNull(dbContext, nameof(dbContext)); Options.DbContext = dbContext; return this; } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Common/Helpers/BaseMockedDbContextFactory.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using rgvlee.Core.Common.Extensions; using rgvlee.Core.Common.Helpers; namespace EntityFrameworkCore.Testing.Common.Helpers { /// /// The base mocked db context factory. /// /// The db context type. public abstract class BaseMockedDbContextFactory where TDbContext : DbContext { /// /// The logger instance. /// protected static readonly ILogger Logger = LoggingHelper.CreateLogger>(); /// /// The parameters that will be used to create the mocked db context and, if one is not provided, /// the in-memory context that the mocked db context will use for in-memory provider supported operations. /// protected readonly List ConstructorParameters; /// /// The db context instance that the mocked db context will use for in-memory provider supported operations. /// protected readonly TDbContext DbContext; /// /// Constructor. /// /// The mocked db context factory options. protected BaseMockedDbContextFactory(MockedDbContextFactoryOptions options) { DbContext = options.DbContext; ConstructorParameters = options.ConstructorParameters?.ToList(); if (ConstructorParameters == null || !ConstructorParameters.Any()) { var dbContextType = typeof(TDbContext); if (!dbContextType.HasConstructor(typeof(DbContextOptions)) && !dbContextType.HasConstructor(typeof(DbContextOptions)) && !dbContextType.HasParameterlessConstructor()) { throw new MissingMethodException(ExceptionMessages.UnableToFindSuitableDbContextConstructor); } if (DbContext != null && dbContextType.HasParameterlessConstructor()) { ConstructorParameters = new List(); } else if (!dbContextType.HasConstructor(typeof(DbContextOptions<>))) { ConstructorParameters = new List { new DbContextOptionsBuilder().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options }; } else if (!dbContextType.HasConstructor(typeof(DbContextOptions))) { ConstructorParameters = new List { new DbContextOptionsBuilder().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options }; } } if (DbContext == null) { DbContext = (TDbContext) Activator.CreateInstance(typeof(TDbContext), ConstructorParameters?.ToArray()); } } /// /// Creates and sets up a mocked db context. /// /// A mocked db context. public abstract TDbContext Create(); } } ================================================ FILE: src/EntityFrameworkCore.Testing.Common/Helpers/ExpressionHelper.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.Extensions.Logging; using rgvlee.Core.Common.Helpers; namespace EntityFrameworkCore.Testing.Common.Helpers { /// /// A helper for expressions. /// public static class ExpressionHelper { private static readonly ILogger Logger = LoggingHelper.CreateLogger(typeof(ExpressionHelper)); /// /// Creates a property expression for the specified property. /// /// The expression parameter. /// The expression property. /// The property info of the property to create the expression for. /// A property expression for the specified property. public static Expression> CreatePropertyExpression(PropertyInfo propertyInfo) { EnsureArgument.IsNotNull(propertyInfo, nameof(propertyInfo)); var parameter = Expression.Parameter(typeof(TParameter)); return Expression.Lambda>(Expression.Property(parameter, propertyInfo), parameter); } public static bool SqlAndParametersMatchFromSqlExpression(string sql, IEnumerable parameters, FromSqlQueryRootExpression expression) { EnsureArgument.IsNotNull(expression, nameof(expression)); EnsureArgument.IsNotNull(parameters, nameof(parameters)); var result = SqlMatchesFromSqlExpression(sql, expression) && ParameterMatchingHelper.DoInvocationParametersMatchSetUpParameters(parameters, (object[]) ((ConstantExpression) expression.Argument).Value); Logger.LogDebug("Match? {result}", result); return result; } private static bool SqlMatchesFromSqlExpression(string sql, FromSqlQueryRootExpression expression) { EnsureArgument.IsNotNull(expression, nameof(expression)); var expressionSql = expression.Sql; var parts = new List(); parts.Add($"Invocation sql: '{expressionSql}'"); parts.Add($"Set up sql: '{sql}'"); Logger.LogDebug(string.Join(Environment.NewLine, parts)); var result = expressionSql.Contains(sql, StringComparison.OrdinalIgnoreCase); Logger.LogDebug("Match? {result}", result); return result; } public static string StringifyFromSqlExpression(FromSqlQueryRootExpression expression) { EnsureArgument.IsNotNull(expression, nameof(expression)); var expressionSql = expression.Sql; var expressionParameters = (object[]) ((ConstantExpression) expression.Argument).Value; var parts = new List(); parts.Add($"Invocation sql: '{expressionSql}'"); parts.Add("Invocation Parameters:"); parts.Add(ParameterMatchingHelper.StringifyParameters(expressionParameters)); return string.Join(Environment.NewLine, parts); } public static void ThrowIfExpressionIsNotSupported(Expression expression) { if (expression is MethodCallExpression mce) { Logger.LogDebug("{methodName} invoked; expression: '{expression}'", mce.Method.Name, mce); if (mce.Method.Name.Equals(nameof(Queryable.ElementAt))) { throw new InvalidOperationException(); } if (mce.Method.Name.Equals(nameof(Queryable.ElementAtOrDefault))) { throw new InvalidOperationException(); } if (mce.Method.Name.Equals(nameof(Queryable.Select))) { var unaryExpression = (UnaryExpression) mce.Arguments[1]; var predicateExpression = unaryExpression.Operand; if (predicateExpression.Type.GetGenericArguments().ToList().Count.Equals(3)) { throw new InvalidOperationException(); } } if (mce.Method.Name.Equals(nameof(Queryable.SkipWhile))) { throw new InvalidOperationException(); } if (mce.Method.Name.Equals(nameof(Queryable.TakeWhile))) { throw new InvalidOperationException(); } } } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Common/Helpers/IMockedDbContextBuilder.cs ================================================ using Microsoft.EntityFrameworkCore; namespace EntityFrameworkCore.Testing.Common.Helpers { /// /// The mocked db context builder. /// /// The db context type. public interface IMockedDbContextBuilder where TDbContext : DbContext { /// /// The mocked db context. /// TDbContext MockedDbContext { get; } /// /// The parameters that will be used to create the mocked db context and, if one is not provided, /// the in-memory context that the mocked db context will use for in-memory provider supported operations. /// /// /// The constructor parameters. /// /// The mocked db context builder. IMockedDbContextBuilder UseConstructorWithParameters(params object[] constructorParameters); /// /// The db context instance that the mocked db context will use for in-memory provider supported operations. /// IMockedDbContextBuilder UseDbContext(TDbContext dbContext); } } ================================================ FILE: src/EntityFrameworkCore.Testing.Common/Helpers/MockedDbContextFactoryOptions.cs ================================================ using System.Collections.Generic; using Microsoft.EntityFrameworkCore; namespace EntityFrameworkCore.Testing.Common.Helpers { /// /// The mocked db context factory options. /// /// The db context type. public class MockedDbContextFactoryOptions where TDbContext : DbContext { /// /// The db context instance that the mocked db context will use for in-memory provider supported operations. /// public TDbContext DbContext { get; set; } /// /// The parameters that will be used to create the mocked db context and, if one is not provided, /// the in-memory context that the mocked db context will use for in-memory provider supported operations. /// public IEnumerable ConstructorParameters { get; set; } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Common/Helpers/ParameterMatchingHelper.cs ================================================ using System; using System.Collections.Generic; using System.Data; using System.Data.Common; using System.Linq; using System.Text; using Microsoft.Extensions.Logging; using rgvlee.Core.Common.Helpers; namespace EntityFrameworkCore.Testing.Common.Helpers { /// /// A helper for parameter matching. /// public class ParameterMatchingHelper { private static readonly ILogger Logger = LoggingHelper.CreateLogger(typeof(ParameterMatchingHelper)); /// /// Determines whether the invocation parameters match the set up parameters. /// /// The set up parameters. /// The invocation parameters. /// true the invocation parameters are a partial or full match of the set up parameters. /// /// If the parameters are DbParameters, parameter name and value are compared. /// Parameter name matching is case insensitive. /// If the value is a string, the matching is case insensitive. /// For everything else an exact match is required. /// public static bool DoInvocationParametersMatchSetUpParameters(IEnumerable setUpParameters, IEnumerable invocationParameters) { var setUpParametersAsList = setUpParameters.ToList(); var invocationParametersAsList = invocationParameters.ToList(); var matches = new Dictionary(); for (var i = 0; i < invocationParametersAsList.Count; i++) { var invocationParameter = invocationParametersAsList[i]; Logger.LogDebug("Checking invocationParameter '{invocationParameter}'", invocationParameter); matches.Add(i, -1); //What was the last set up parameter matched? var startAt = matches.Any() ? matches.Max(x => x.Value) + 1 : 0; Logger.LogDebug("startAt: {startAt}", startAt); for (var j = 0; j < setUpParametersAsList.Count; j++) { var setUpParameter = setUpParametersAsList[j]; Logger.LogDebug("Checking setUpParameter '{setUpParameter}'", setUpParameter); if (invocationParameter is DbParameter dbInvocationParameter && setUpParameter is DbParameter dbSetUpParameter && DoesInvocationParameterMatchSetUpParameter(dbSetUpParameter, dbInvocationParameter)) { matches[i] = j; break; } if (DoesInvocationParameterValueMatchSetUpParameterValue(setUpParameter, invocationParameter)) { matches[i] = j; break; } } } Logger.LogDebug("Match summary '{summary}'", string.Join(Environment.NewLine, matches.Select(x => $"{x.Key}: {x.Value}"))); return matches.Count(x => x.Value > -1) >= setUpParametersAsList.Count; } private static bool DoesInvocationParameterValueMatchSetUpParameterValue(object setUpParameter, object invocationParameter) { if (invocationParameter == setUpParameter) { return true; } if (invocationParameter != null && setUpParameter != null && invocationParameter.Equals(setUpParameter)) { return true; } if (invocationParameter is string stringInvocationParameterValue && setUpParameter is string stringSetUpParameterValue && stringInvocationParameterValue.Equals(stringSetUpParameterValue, StringComparison.OrdinalIgnoreCase)) { return true; } return false; } private static bool DoesInvocationParameterMatchSetUpParameter(IDataParameter setUpParameter, IDataParameter invocationParameter) { var setUpParameterParameterName = setUpParameter.ParameterName ?? string.Empty; var invocationParameterParameterName = invocationParameter.ParameterName ?? string.Empty; if (!invocationParameterParameterName.Equals(setUpParameterParameterName, StringComparison.OrdinalIgnoreCase)) { return false; } return DoesInvocationParameterValueMatchSetUpParameterValue(setUpParameter.Value, invocationParameter.Value); } /// /// Converts a sequence of invocation parameters to a string of parameter names and values. /// /// The invocation parameters. /// A string of parameter names and values. public static string StringifyParameters(IEnumerable invocationParameters) { var invocationParametersAsList = invocationParameters.ToList(); var parts = new List(); for (var i = 0; i < invocationParametersAsList.Count; i++) { var invocationParameter = invocationParametersAsList[i]; var sb = new StringBuilder(); switch (invocationParameter) { case DbParameter dbInvocationParameter: { sb.Append(dbInvocationParameter.ParameterName); sb.Append(": "); if (dbInvocationParameter.Value == null) { sb.Append("null"); } else { sb.Append(dbInvocationParameter.Value); } break; } case null: sb.Append("Parameter "); sb.Append(i); sb.Append(": null"); break; default: sb.Append("Parameter "); sb.Append(i); sb.Append(": "); sb.Append(invocationParameter); break; } parts.Add(sb.ToString()); } return string.Join(Environment.NewLine, parts); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Common/QueryRootExpression.cs ================================================ using System; using System.Linq; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query; namespace EntityFrameworkCore.Testing.Common { public class FakeQueryRootExpression : EntityQueryRootExpression { public FakeQueryRootExpression(IAsyncQueryProvider asyncQueryProvider, IEntityType entityType) : base(asyncQueryProvider, entityType) { Type = typeof(IOrderedQueryable<>).MakeGenericType(entityType.ClrType); } public override Type Type { get; } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Common.Tests/AsyncEnumerableTests.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using AutoFixture; using NUnit.Framework; namespace EntityFrameworkCore.Testing.Common.Tests { public class AsyncEnumerableTests : BaseForQueryableTests { private IQueryable _source; protected override IQueryable Queryable => _source; [SetUp] public override void SetUp() { base.SetUp(); _source = new AsyncEnumerable(new List()); } protected override void SeedQueryableSource() { var itemsToAdd = Fixture.Build().With(p => p.CreatedAt, DateTime.Today).With(p => p.LastModifiedAt, DateTime.Today).CreateMany().ToList(); _source = new AsyncEnumerable(itemsToAdd); ItemsAddedToQueryableSource = itemsToAdd; } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Common.Tests/BaseForDbContextTests.cs ================================================ using System; using System.Collections.Generic; using Microsoft.Data.SqlClient; using System.Linq; using System.Threading.Tasks; using AutoFixture; using FluentAssertions; using Microsoft.EntityFrameworkCore; using NUnit.Framework; namespace EntityFrameworkCore.Testing.Common.Tests { public abstract class BaseForDbContextTests : BaseForTests where TDbContext : DbContext { protected TDbContext MockedDbContext; public abstract void AddExecuteSqlInterpolatedResult(TDbContext mockedDbContext, int expectedResult); public abstract void AddExecuteSqlInterpolatedResult(TDbContext mockedDbContext, FormattableString sql, int expectedResult); public abstract void AddExecuteSqlInterpolatedResult(TDbContext mockedDbContext, string sql, IEnumerable parameters, int expectedResult); public abstract void AddExecuteSqlRawResult(TDbContext mockedDbContext, int expectedResult); public abstract void AddExecuteSqlRawResult(TDbContext mockedDbContext, string sql, int expectedResult); public abstract void AddExecuteSqlRawResult(TDbContext mockedDbContext, string sql, IEnumerable parameters, int expectedResult); [Test] public void ExecuteSqlInterpolated_AnySql_ReturnsExpectedResult() { var expectedResult = 1; AddExecuteSqlInterpolatedResult(MockedDbContext, expectedResult); var actualResult1 = MockedDbContext.Database.ExecuteSqlInterpolated($"sp_NoParams"); var actualResult2 = MockedDbContext.Database.ExecuteSqlInterpolated($"sp_NoParams"); Assert.Multiple(() => { Assert.That(actualResult1, Is.EqualTo(expectedResult)); Assert.That(actualResult2, Is.EqualTo(actualResult1)); }); } [Test] public void ExecuteSqlInterpolated_SpecifiedFormattableStringWithSqlParameterParameters_ReturnsExpectedResult() { var sql = "sp_WithParams"; var parameters = new List { new("@SomeParameter2", "Value2") }; var expectedResult = 1; AddExecuteSqlInterpolatedResult(MockedDbContext, sql, parameters, expectedResult); var actualResult1 = MockedDbContext.Database.ExecuteSqlInterpolated($"[dbo].[sp_WithParams] {parameters[0]} {Fixture.Create()}"); var actualResult2 = MockedDbContext.Database.ExecuteSqlInterpolated($"[dbo].[sp_WithParams] {parameters[0]} {Fixture.Create()}"); Assert.Multiple(() => { Assert.That(actualResult1, Is.EqualTo(expectedResult)); Assert.That(actualResult2, Is.EqualTo(actualResult1)); }); } [Test] public void ExecuteSqlInterpolated_SpecifiedFormattableStringWithSqlParameterParametersThatDoNotMatchSetUp_ThrowsException() { var sql = "sp_WithParams"; var setUpParameters = new List { new("@SomeParameter3", "Value3") }; var invocationParameters = new List { new("@SomeParameter1", "Value1"), new("@SomeParameter2", "Value2") }; var expectedResult = 1; AddExecuteSqlInterpolatedResult(MockedDbContext, sql, setUpParameters, expectedResult); Assert.Throws(() => { var actualResult1 = MockedDbContext.Database.ExecuteSqlInterpolated($"[dbo].[sp_WithParams] {invocationParameters[0]}, {invocationParameters[1]}"); }); Assert.Throws(() => { var actualResult2 = MockedDbContext.Database.ExecuteSqlInterpolated($"[dbo].[sp_WithParams] {invocationParameters[0]}, {invocationParameters[1]}"); }); } [Test] public void ExecuteSqlInterpolated_SpecifiedSql_ReturnsExpectedResult() { var sql = (FormattableString) $"sp_NoParams"; var expectedResult = 1; AddExecuteSqlInterpolatedResult(MockedDbContext, sql, expectedResult); var actualResult1 = MockedDbContext.Database.ExecuteSqlInterpolated($"sp_NoParams"); var actualResult2 = MockedDbContext.Database.ExecuteSqlInterpolated($"sp_NoParams"); Assert.Multiple(() => { Assert.That(actualResult1, Is.EqualTo(expectedResult)); Assert.That(actualResult2, Is.EqualTo(actualResult1)); }); } [Test] public void ExecuteSqlInterpolated_SpecifiedSqlThatDoesNotMatchSetUp_ThrowsException() { var sql = (FormattableString) $"asdf"; var expectedResult = 1; AddExecuteSqlInterpolatedResult(MockedDbContext, sql, expectedResult); Assert.Throws(() => { var actualResult = MockedDbContext.Database.ExecuteSqlInterpolated($"sp_NoParams"); }); } [Test] public void ExecuteSqlInterpolated_WithNoMatchesAdded_ThrowsException() { Assert.Throws(() => { var actualResult = MockedDbContext.Database.ExecuteSqlInterpolated($"sp_NoParams"); }); } [Test] public async Task ExecuteSqlInterpolatedAsync_AnySql_ReturnsExpectedResult() { var expectedResult = 1; AddExecuteSqlInterpolatedResult(MockedDbContext, expectedResult); var actualResult1 = await MockedDbContext.Database.ExecuteSqlInterpolatedAsync($"sp_NoParams"); var actualResult2 = await MockedDbContext.Database.ExecuteSqlInterpolatedAsync($"sp_NoParams"); Assert.Multiple(() => { Assert.That(actualResult1, Is.EqualTo(expectedResult)); Assert.That(actualResult2, Is.EqualTo(actualResult1)); }); } [Test] public async Task ExecuteSqlInterpolatedAsync_SpecifiedFormattableStringWithSqlParameterParameters_ReturnsExpectedResult() { var sql = "sp_WithParams"; var parameters = new List { new("@SomeParameter2", "Value2") }; var expectedResult = 1; AddExecuteSqlInterpolatedResult(MockedDbContext, sql, parameters, expectedResult); var actualResult1 = await MockedDbContext.Database.ExecuteSqlInterpolatedAsync($"[dbo].[sp_WithParams] {parameters[0]} {Fixture.Create()}"); var actualResult2 = await MockedDbContext.Database.ExecuteSqlInterpolatedAsync($"[dbo].[sp_WithParams] {parameters[0]} {Fixture.Create()}"); Assert.Multiple(() => { Assert.That(actualResult1, Is.EqualTo(expectedResult)); Assert.That(actualResult2, Is.EqualTo(actualResult1)); }); } [Test] public async Task ExecuteSqlInterpolatedAsync_SpecifiedFormattableStringWithStringParameters_ReturnsExpectedResult() { var sql = "sp_WithParams"; var parameters = new List { "Value2" }; var expectedResult = 1; AddExecuteSqlInterpolatedResult(MockedDbContext, sql, parameters, expectedResult); var actualResult1 = await MockedDbContext.Database.ExecuteSqlInterpolatedAsync($"[dbo].[sp_WithParams] {parameters[0]} {Fixture.Create()}"); var actualResult2 = await MockedDbContext.Database.ExecuteSqlInterpolatedAsync($"[dbo].[sp_WithParams] {parameters[0]} {Fixture.Create()}"); Assert.Multiple(() => { Assert.That(actualResult1, Is.EqualTo(expectedResult)); Assert.That(actualResult2, Is.EqualTo(actualResult1)); }); } [Test] public async Task ExecuteSqlInterpolatedAsync_SpecifiedSql_ReturnsExpectedResult() { var sql = (FormattableString) $"sp_NoParams"; var expectedResult = 1; AddExecuteSqlInterpolatedResult(MockedDbContext, sql, expectedResult); var actualResult1 = await MockedDbContext.Database.ExecuteSqlInterpolatedAsync($"sp_NoParams"); var actualResult2 = await MockedDbContext.Database.ExecuteSqlInterpolatedAsync($"sp_NoParams"); Assert.Multiple(() => { Assert.That(actualResult1, Is.EqualTo(expectedResult)); Assert.That(actualResult2, Is.EqualTo(actualResult1)); }); } [Test] public void ExecuteSqlInterpolatedAsync_SpecifiedSqlThatDoesNotMatchSetUp_ThrowsException() { var sql = (FormattableString) $"asdf"; var expectedResult = 1; AddExecuteSqlInterpolatedResult(MockedDbContext, sql, expectedResult); Assert.ThrowsAsync(async () => { var actualResult = await MockedDbContext.Database.ExecuteSqlInterpolatedAsync($"sp_NoParams"); }); } [Test] public void ExecuteSqlInterpolatedUsingFormattableStringSetUp_SpecifiedFormattableStringWithStringParameters_ReturnsExpectedResult() { var parameters = new List { "Value2" }; var sql = (FormattableString) $"[sp_WithParams] {parameters[0]}"; var expectedResult = 1; AddExecuteSqlInterpolatedResult(MockedDbContext, sql, expectedResult); var actualResult1 = MockedDbContext.Database.ExecuteSqlInterpolated($"[dbo].[sp_WithParams] {parameters[0]} {Fixture.Create()}"); var actualResult2 = MockedDbContext.Database.ExecuteSqlInterpolated($"[dbo].[sp_WithParams] {parameters[0]} {Fixture.Create()}"); Assert.Multiple(() => { Assert.That(actualResult1, Is.EqualTo(expectedResult)); Assert.That(actualResult2, Is.EqualTo(actualResult1)); }); } [Test] public void ExecuteSqlInterpolatedUsingFormattableStringSetUp_SpecifiedFormattableStringWithStringParametersThatDoesNotMatchSetUp_ThrowsException() { var parameters = new List { "Value2" }; var sql = (FormattableString) $"[sp_WithParams] {parameters[0]}"; var expectedResult = 1; AddExecuteSqlInterpolatedResult(MockedDbContext, sql, expectedResult); var actualResult1 = MockedDbContext.Database.ExecuteSqlInterpolated($"[dbo].[sp_WithParams] {Fixture.Create()} {parameters[0]}"); var actualResult2 = MockedDbContext.Database.ExecuteSqlInterpolated($"[dbo].[sp_WithParams] {Fixture.Create()} {parameters[0]}"); Assert.Multiple(() => { Assert.That(actualResult1, Is.EqualTo(expectedResult)); Assert.That(actualResult2, Is.EqualTo(actualResult1)); }); } [Test] public void ExecuteSqlInterpolatedUsingSqlAndParameterSetUp_SpecifiedFormattableStringWithStringParameters_ReturnsExpectedResult() { var sql = "sp_WithParams"; var parameters = new List { "Value2" }; var expectedResult = 1; AddExecuteSqlInterpolatedResult(MockedDbContext, sql, parameters, expectedResult); var actualResult1 = MockedDbContext.Database.ExecuteSqlInterpolated($"[dbo].[sp_WithParams] {parameters[0]} {Fixture.Create()}"); var actualResult2 = MockedDbContext.Database.ExecuteSqlInterpolated($"[dbo].[sp_WithParams] {parameters[0]} {Fixture.Create()}"); Assert.Multiple(() => { Assert.That(actualResult1, Is.EqualTo(expectedResult)); Assert.That(actualResult2, Is.EqualTo(actualResult1)); }); } [Test] public void ExecuteSqlRaw_AnySql_ReturnsExpectedResult() { var expectedResult = 1; AddExecuteSqlRawResult(MockedDbContext, expectedResult); var actualResult1 = MockedDbContext.Database.ExecuteSqlRaw("sp_NoParams"); var actualResult2 = MockedDbContext.Database.ExecuteSqlRaw("sp_NoParams"); Assert.Multiple(() => { Assert.That(actualResult1, Is.EqualTo(expectedResult)); Assert.That(actualResult2, Is.EqualTo(actualResult1)); }); } [Test] public void ExecuteSqlRaw_SpecifiedSql_ReturnsExpectedResult() { var sql = "sp_NoParams"; var expectedResult = 1; AddExecuteSqlRawResult(MockedDbContext, sql, expectedResult); var actualResult1 = MockedDbContext.Database.ExecuteSqlRaw("sp_NoParams"); var actualResult2 = MockedDbContext.Database.ExecuteSqlRaw("sp_NoParams"); Assert.Multiple(() => { Assert.That(actualResult1, Is.EqualTo(expectedResult)); Assert.That(actualResult2, Is.EqualTo(actualResult1)); }); } [Test] public void ExecuteSqlRaw_SpecifiedSqlThatDoesNotMatchSetUp_ThrowsException() { var sql = "asdf"; var expectedResult = 1; AddExecuteSqlRawResult(MockedDbContext, sql, expectedResult); Assert.Throws(() => { var actualResult = MockedDbContext.Database.ExecuteSqlRaw("sp_NoParams"); }); } [Test] public void ExecuteSqlRaw_SpecifiedSqlWithSqlParameterParameters_ReturnsExpectedResult() { var sql = "sp_WithParams"; var parameters = new List { new("@SomeParameter2", "Value2") }; var expectedResult = 1; AddExecuteSqlRawResult(MockedDbContext, sql, parameters, expectedResult); var actualResult1 = MockedDbContext.Database.ExecuteSqlRaw("[dbo].[sp_WithParams] @SomeParameter1 @SomeParameter2", parameters); var actualResult2 = MockedDbContext.Database.ExecuteSqlRaw("[dbo].[sp_WithParams] @SomeParameter1 @SomeParameter2", parameters); Assert.Multiple(() => { Assert.That(actualResult1, Is.EqualTo(expectedResult)); Assert.That(actualResult2, Is.EqualTo(actualResult1)); }); } [Test] public void ExecuteSqlRaw_SpecifiedSqlWithSqlParameterParametersThatDoNotMatchSetUp_ThrowsException() { var sql = "sp_WithParams"; var setUpParameters = new List { new("@SomeParameter3", "Value3") }; var invocationParameters = new List { new("@SomeParameter1", "Value1"), new("@SomeParameter2", "Value2") }; var expectedResult = 1; AddExecuteSqlRawResult(MockedDbContext, sql, setUpParameters, expectedResult); Assert.Throws(() => { var actualResult1 = MockedDbContext.Database.ExecuteSqlRaw("[dbo].[sp_WithParams] @SomeParameter1 @SomeParameter2", invocationParameters); }); Assert.Throws(() => { var actualResult2 = MockedDbContext.Database.ExecuteSqlRaw("[dbo].[sp_WithParams] @SomeParameter1 @SomeParameter2", invocationParameters); }); } [Test] public void ExecuteSqlRaw_SpecifiedSqlWithStringParameters_ReturnsExpectedResult() { var sql = "sp_WithParams"; var parameters = new List { "Value2" }; var expectedResult = 1; AddExecuteSqlRawResult(MockedDbContext, sql, parameters, expectedResult); var actualResult1 = MockedDbContext.Database.ExecuteSqlRaw("[dbo].[sp_WithParams] @SomeParameter1 @SomeParameter2", parameters); var actualResult2 = MockedDbContext.Database.ExecuteSqlRaw("[dbo].[sp_WithParams] @SomeParameter1 @SomeParameter2", parameters); Assert.Multiple(() => { Assert.That(actualResult1, Is.EqualTo(expectedResult)); Assert.That(actualResult2, Is.EqualTo(actualResult1)); }); } [Test] public void ExecuteSqlRaw_WithNoMatchesAdded_ThrowsException() { Assert.Throws(() => { var actualResult = MockedDbContext.Database.ExecuteSqlRaw("sp_NoParams"); }); } [Test] public async Task ExecuteSqlRawAsync_AnySql_ReturnsExpectedResult() { var expectedResult = 1; AddExecuteSqlRawResult(MockedDbContext, expectedResult); var actualResult1 = await MockedDbContext.Database.ExecuteSqlRawAsync("sp_NoParams"); var actualResult2 = await MockedDbContext.Database.ExecuteSqlRawAsync("sp_NoParams"); Assert.Multiple(() => { Assert.That(actualResult1, Is.EqualTo(expectedResult)); Assert.That(actualResult2, Is.EqualTo(actualResult1)); }); } [Test] public async Task ExecuteSqlRawAsync_SpecifiedSql_ReturnsExpectedResult() { var sql = "sp_NoParams"; var expectedResult = 1; AddExecuteSqlRawResult(MockedDbContext, sql, expectedResult); var actualResult1 = await MockedDbContext.Database.ExecuteSqlRawAsync("sp_NoParams"); var actualResult2 = await MockedDbContext.Database.ExecuteSqlRawAsync("sp_NoParams"); Assert.Multiple(() => { Assert.That(actualResult1, Is.EqualTo(expectedResult)); Assert.That(actualResult2, Is.EqualTo(actualResult1)); }); } [Test] public void ExecuteSqlRawAsync_SpecifiedSqlThatDoesNotMatchSetUp_ThrowsException() { var sql = "asdf"; var expectedResult = 1; AddExecuteSqlRawResult(MockedDbContext, sql, expectedResult); Assert.ThrowsAsync(async () => { var actualResult = await MockedDbContext.Database.ExecuteSqlRawAsync("sp_NoParams"); }); } [Test] public async Task ExecuteSqlRawAsync_SpecifiedSqlWithSqlParameterParameters_ReturnsExpectedResult() { var sql = "sp_WithParams"; var parameters = new List { new("@SomeParameter2", "Value2") }; var expectedResult = 1; AddExecuteSqlRawResult(MockedDbContext, sql, parameters, expectedResult); var actualResult1 = await MockedDbContext.Database.ExecuteSqlRawAsync("[dbo].[sp_WithParams] @SomeParameter2", parameters); var actualResult2 = await MockedDbContext.Database.ExecuteSqlRawAsync("[dbo].[sp_WithParams] @SomeParameter2", parameters); Assert.Multiple(() => { Assert.That(actualResult1, Is.EqualTo(expectedResult)); Assert.That(actualResult2, Is.EqualTo(actualResult1)); }); } [Test] public async Task ExecuteSqlRawAsync_SpecifiedSqlWithStringParameters_ReturnsExpectedResult() { var sql = "sp_WithParams"; var parameters = new List { "Value2" }; var expectedResult = 1; AddExecuteSqlRawResult(MockedDbContext, sql, parameters, expectedResult); var actualResult1 = await MockedDbContext.Database.ExecuteSqlRawAsync("[dbo].[sp_WithParams] @SomeParameter2", parameters); var actualResult2 = await MockedDbContext.Database.ExecuteSqlRawAsync("[dbo].[sp_WithParams] @SomeParameter2", parameters); Assert.Multiple(() => { Assert.That(actualResult1, Is.EqualTo(expectedResult)); Assert.That(actualResult2, Is.EqualTo(actualResult1)); }); } [Test] public void Set_TypeNotIncludedInModel_ThrowsException() { Assert.Multiple(() => { var ex = Assert.Throws(() => MockedDbContext.Set().ToList()); Assert.That(ex.Message, Is.EqualTo(string.Format(ExceptionMessages.CannotCreateDbSetTypeNotIncludedInModel, nameof(NotRegisteredEntity)))); }); } [Test] public virtual void SetCommandTimeout_ValidTimeout_DoesNotThrowException() { Assert.DoesNotThrow(() => { MockedDbContext.Database.SetCommandTimeout(60); }); } [Test] public virtual void GetCommandTimeout_ReturnsZero() { var actualResult = MockedDbContext.Database.GetCommandTimeout(); actualResult.Should().Be(0); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Common.Tests/BaseForDbSetTests.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using AutoFixture; using Microsoft.EntityFrameworkCore; using NUnit.Framework; namespace EntityFrameworkCore.Testing.Common.Tests { public abstract class BaseForDbSetTests : BaseForMockedQueryableTests where TDbContext : DbContext where TEntity : BaseTestEntity { protected TDbContext MockedDbContext; [SetUp] public override void SetUp() { base.SetUp(); MockedDbContext = CreateMockedDbContext(); } [TearDown] public override void TearDown() { MockedDbContext.Dispose(); base.TearDown(); } protected override void SeedQueryableSource() { var itemsToAdd = Fixture.Build().With(p => p.CreatedAt, DateTime.Today).With(p => p.LastModifiedAt, DateTime.Today).CreateMany().ToList(); DbSet.AddRange(itemsToAdd); MockedDbContext.SaveChanges(); ItemsAddedToQueryableSource = itemsToAdd; } protected abstract TDbContext CreateMockedDbContext(); [Test] public virtual void AddAndPersist_Item_AddsAndPersistsItem() { var expectedResult = Fixture.Create(); DbSet.Add(expectedResult); MockedDbContext.SaveChanges(); Assert.Multiple(() => { Assert.That(DbSet.Single(), Is.EqualTo(expectedResult)); Assert.That(DbSet.Single(), Is.EqualTo(expectedResult)); }); } [Test] public virtual void AddAndPersist_Items_AddsAndPersistsItems() { var expectedResult = Fixture.CreateMany().ToList(); DbSet.AddRange(expectedResult); MockedDbContext.SaveChanges(); var actualResult = DbSet.ToList(); Assert.Multiple(() => { Assert.That(actualResult, Is.EquivalentTo(expectedResult)); Assert.That(DbSet.ToList(), Is.EquivalentTo(actualResult)); }); } [Test] public virtual async Task AddAndPersistAsync_Item_AddsAndPersistsItem() { var expectedResult = Fixture.Create(); await DbSet.AddAsync(expectedResult); await MockedDbContext.SaveChangesAsync(); Assert.Multiple(() => { Assert.That(DbSet.Single(), Is.EqualTo(expectedResult)); Assert.That(DbSet.Single(), Is.EqualTo(expectedResult)); }); } [Test] public virtual async Task AddAndPersistAsync_Items_AddsAndPersistsItems() { var expectedResult = Fixture.CreateMany().ToList(); await DbSet.AddRangeAsync(expectedResult); await MockedDbContext.SaveChangesAsync(); var actualResult = DbSet.ToList(); Assert.Multiple(() => { Assert.That(actualResult, Is.EquivalentTo(expectedResult)); Assert.That(DbSet.ToList(), Is.EquivalentTo(actualResult)); }); } [Test] public virtual void AddThenSingleThenAddRangeThenToListThenWhereThenSelect_ReturnsExpectedResults() { var items = Fixture.CreateMany().ToList(); DbSet.Add(items[0]); MockedDbContext.SaveChanges(); var singleResult = DbSet.Single(); DbSet.AddRange(items.Skip(1)); MockedDbContext.SaveChanges(); var toListResult = DbSet.ToList(); var selectedItem = items.Last(); var whereResult = DbSet.Where(x => x.Equals(selectedItem)).ToList(); var selectResult = DbSet.Select(x => new { Item = x }).ToList(); Assert.Multiple(() => { Assert.That(singleResult, Is.EqualTo(items[0])); Assert.That(toListResult, Is.EquivalentTo(items)); Assert.That(whereResult, Is.EquivalentTo(new List { selectedItem })); for (var i = 0; i < items.Count; i++) { Assert.That(selectResult[i].Item, Is.EqualTo(items[i])); } }); } [Test] public virtual void AnyThenAddThenPersistThenAny_ReturnsFalseThenTrue() { var actualResult1 = DbSet.Any(); DbSet.Add(Fixture.Create()); MockedDbContext.SaveChanges(); var actualResult2 = DbSet.Any(); Assert.Multiple(() => { Assert.That(actualResult1, Is.False); Assert.That(actualResult2, Is.True); }); } [Test] public virtual async Task AsAsyncEnumerable_ReturnsAsyncEnumerable() { var expectedResult = Fixture.Create(); DbSet.Add(expectedResult); MockedDbContext.SaveChanges(); var asyncEnumerable = DbSet.AsAsyncEnumerable(); var actualResults = new List(); await foreach (var item in asyncEnumerable) { actualResults.Add(item); } Assert.Multiple(() => { Assert.That(actualResults.Single(), Is.EqualTo(expectedResult)); Assert.That(actualResults.Single(), Is.EqualTo(expectedResult)); }); } [Test] public virtual void AsQueryable_ReturnsQueryable() { var expectedResult = Fixture.Create(); DbSet.Add(expectedResult); MockedDbContext.SaveChanges(); var queryable = DbSet.AsQueryable(); Assert.Multiple(() => { Assert.That(queryable.Single(), Is.EqualTo(expectedResult)); Assert.That(queryable.Single(), Is.EqualTo(expectedResult)); }); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Common.Tests/BaseForMockedQueryableTests.cs ================================================ using System; using System.Collections.Generic; using System.ComponentModel; using Microsoft.Data.SqlClient; using System.Linq; using System.Threading.Tasks; using AutoFixture; using Microsoft.EntityFrameworkCore; using NUnit.Framework; namespace EntityFrameworkCore.Testing.Common.Tests { public abstract class BaseForMockedQueryableTests : BaseForQueryableTests where TEntity : BaseTestEntity { protected DbSet DbSet => (DbSet) Queryable; protected abstract void AddFromSqlRawResult(DbSet mockedDbSet, IEnumerable expectedResult); protected abstract void AddFromSqlRawResult(DbSet mockedDbSet, string sql, IEnumerable expectedResult); protected abstract void AddFromSqlRawResult(DbSet mockedDbSet, string sql, IEnumerable parameters, IEnumerable expectedResult); protected abstract void AddFromSqlInterpolatedResult(DbSet mockedDbSet, IEnumerable expectedResult); protected abstract void AddFromSqlInterpolatedResult(DbSet mockedDbSet, FormattableString sql, IEnumerable expectedResult); protected abstract void AddFromSqlInterpolatedResult(DbSet mockedDbSet, string sql, IEnumerable parameters, IEnumerable expectedResult); [Test] public virtual void FormattableStringSetUpFromSqlInterpolated_SpecifiedSqlWithStringParameters_ReturnsExpectedResult() { var parameters = new List { "Value2" }; var sql = (FormattableString) $"[sp_WithParams] {parameters[0]}"; var expectedResult = Fixture.CreateMany().ToList(); AddFromSqlInterpolatedResult(DbSet, sql, expectedResult); var actualResult1 = DbSet.FromSqlInterpolated($"[dbo].[sp_WithParams] {parameters[0]}").ToList(); var actualResult2 = DbSet.FromSqlInterpolated($"[dbo].[sp_WithParams] {parameters[0]}").ToList(); Assert.Multiple(() => { Assert.That(actualResult1, Is.EquivalentTo(expectedResult)); Assert.That(actualResult2, Is.EquivalentTo(actualResult1)); }); } [Test] public virtual void FromSqlInterpolated_AnySql_ReturnsExpectedResult() { var expectedResult = Fixture.CreateMany().ToList(); AddFromSqlInterpolatedResult(DbSet, expectedResult); var actualResult1 = DbSet.FromSqlInterpolated($"sp_NoParams").ToList(); var actualResult2 = DbSet.FromSqlInterpolated($"sp_NoParams").ToList(); Assert.Multiple(() => { Assert.That(actualResult1, Is.EquivalentTo(expectedResult)); Assert.That(actualResult2, Is.EquivalentTo(actualResult1)); }); } [Test] public virtual void FromSqlInterpolated_SpecifiedSql_ReturnsExpectedResult() { var sql = (FormattableString) $"sp_NoParams"; var expectedResult = Fixture.CreateMany().ToList(); AddFromSqlInterpolatedResult(DbSet, sql, expectedResult); var actualResult1 = DbSet.FromSqlInterpolated($"[dbo].[sp_NoParams]").ToList(); var actualResult2 = DbSet.FromSqlInterpolated($"sp_NoParams").ToList(); Assert.Multiple(() => { Assert.That(actualResult1, Is.EquivalentTo(expectedResult)); Assert.That(actualResult2, Is.EquivalentTo(actualResult1)); }); } [Test] public virtual void FromSqlInterpolated_SpecifiedSqlThatDoesNotMatchSetUp_ThrowsException() { var sql = (FormattableString) $"asdf"; var expectedResult = Fixture.CreateMany().ToList(); AddFromSqlInterpolatedResult(DbSet, sql, expectedResult); Assert.Throws(() => { var actualResult = DbSet.FromSqlInterpolated($"sp_NoParams").ToList(); }); } [Test] public virtual void FromSqlInterpolated_SpecifiedSqlWithSqlParameterParameters_ReturnsExpectedResult() { var sql = "sp_WithParams"; var parameters = new List { new("@SomeParameter2", "Value2") }; var expectedResult = Fixture.CreateMany().ToList(); AddFromSqlInterpolatedResult(DbSet, sql, parameters, expectedResult); var actualResult1 = DbSet.FromSqlInterpolated($"[dbo].[sp_WithParams] {Fixture.Create()}, {parameters[0]}").ToList(); var actualResult2 = DbSet.FromSqlInterpolated($"sp_WithParams {Fixture.Create()}, {parameters[0]}").ToList(); Assert.Multiple(() => { Assert.That(actualResult1, Is.EquivalentTo(expectedResult)); Assert.That(actualResult2, Is.EquivalentTo(actualResult1)); }); } [Test] public virtual void FromSqlInterpolated_SpecifiedSqlWithSqlParameterParametersThatDoNotMatchSetUp_ThrowsException() { var sql = "sp_WithParams"; var setUpParameters = new List { new("@SomeParameter3", "Value3") }; var invocationParameters = new List { new("@SomeParameter1", "Value1"), new("@SomeParameter2", "Value2") }; var expectedResult = Fixture.CreateMany().ToList(); AddFromSqlInterpolatedResult(DbSet, sql, setUpParameters, expectedResult); Assert.Throws(() => { var actualResult1 = DbSet.FromSqlInterpolated($"[dbo].[sp_WithParams] {invocationParameters[0]}, {invocationParameters[1]}").ToList(); }); Assert.Throws(() => { var actualResult2 = DbSet.FromSqlInterpolated($"sp_WithParams {invocationParameters[0]}, {invocationParameters[1]}").ToList(); }); } [Test] public virtual void FromSqlInterpolated_SpecifiedSqlWithStringParameters_ReturnsExpectedResult() { var sql = "sp_WithParams"; var parameters = new List { "Value2" }; var expectedResult = Fixture.CreateMany().ToList(); AddFromSqlInterpolatedResult(DbSet, sql, parameters, expectedResult); var actualResult1 = DbSet.FromSqlInterpolated($"[dbo].[sp_WithParams] {Fixture.Create()}, {parameters[0]}").ToList(); var actualResult2 = DbSet.FromSqlInterpolated($"sp_WithParams {Fixture.Create()}, {parameters[0]}").ToList(); Assert.Multiple(() => { Assert.That(actualResult1, Is.EquivalentTo(expectedResult)); Assert.That(actualResult2, Is.EquivalentTo(actualResult1)); }); } [Test] public virtual void FromSqlInterpolated_ThrowsException() { Assert.Throws(() => { var actualResult = DbSet.FromSqlInterpolated($"sp_NoParams").ToList(); }); } [Test] public virtual void FromSqlRaw_AnySql_ReturnsExpectedResult() { var expectedResult = Fixture.CreateMany().ToList(); AddFromSqlRawResult(DbSet, expectedResult); var actualResult1 = DbSet.FromSqlRaw("sp_NoParams").ToList(); var actualResult2 = DbSet.FromSqlRaw("sp_NoParams").ToList(); Assert.Multiple(() => { Assert.That(actualResult1, Is.EquivalentTo(expectedResult)); Assert.That(actualResult2, Is.EquivalentTo(actualResult1)); }); } [Test] public virtual void FromSqlRaw_QueryProviderWithManyFromSqlResults_ReturnsExpectedResults() { var sql1 = "sp_NoParams"; var expectedResult1 = Fixture.CreateMany().ToList(); var sql2 = "sp_WithParams"; var parameters2 = new List { new("@SomeParameter1", "Value1"), new("@SomeParameter2", "Value2") }; var expectedResult2 = Fixture.CreateMany().ToList(); AddFromSqlRawResult(DbSet, sql1, expectedResult1); AddFromSqlRawResult(DbSet, sql2, parameters2, expectedResult2); Console.WriteLine("actualResult1"); var actualResult1 = DbSet.FromSqlRaw("[dbo].[sp_NoParams]").ToList(); Console.WriteLine("actualResult2"); var actualResult2 = DbSet.FromSqlRaw("[dbo].[sp_WithParams]", parameters2.ToArray()).ToList(); Assert.Multiple(() => { Assert.That(actualResult1, Is.EquivalentTo(expectedResult1)); Assert.That(actualResult2, Is.EquivalentTo(expectedResult2)); }); } [Test] public virtual void FromSqlRaw_SpecifiedSql_ReturnsExpectedResult() { var sql = "sp_NoParams"; var expectedResult = Fixture.CreateMany().ToList(); AddFromSqlRawResult(DbSet, sql, expectedResult); var actualResult1 = DbSet.FromSqlRaw("[dbo].[sp_NoParams]").ToList(); var actualResult2 = DbSet.FromSqlRaw("sp_NoParams").ToList(); Assert.Multiple(() => { Assert.That(actualResult1, Is.EquivalentTo(expectedResult)); Assert.That(actualResult2, Is.EquivalentTo(actualResult1)); }); } [Test] public virtual void FromSqlRaw_SpecifiedSqlThatDoesNotMatchSetUp_ThrowsException() { var sql = "asdf"; var expectedResult = Fixture.CreateMany().ToList(); AddFromSqlRawResult(DbSet, sql, expectedResult); Assert.Throws(() => { var actualResult = DbSet.FromSqlRaw("sp_NoParams").ToList(); }); } [Test] public virtual void FromSqlRaw_SpecifiedSqlWithSqlParameterParameters_ReturnsExpectedResult() { var sql = "sp_WithParams"; var parameters = new List { new("@SomeParameter2", "Value2") }; var expectedResult = Fixture.CreateMany().ToList(); AddFromSqlRawResult(DbSet, sql, parameters, expectedResult); var actualResult1 = DbSet.FromSqlRaw("[dbo].[sp_WithParams] @SomeParameter1 @SomeParameter2", parameters.ToArray()).ToList(); var actualResult2 = DbSet.FromSqlRaw("sp_WithParams @SomeParameter1 @SomeParameter2", parameters.ToArray()).ToList(); Assert.Multiple(() => { Assert.That(actualResult1, Is.EquivalentTo(expectedResult)); Assert.That(actualResult2, Is.EquivalentTo(actualResult1)); }); } [Test] public virtual void FromSqlRaw_SpecifiedSqlWithSqlParameterParametersThatDoNotMatchSetUp_ThrowsException() { var sql = "sp_WithParams"; var setUpParameters = new List { new("@SomeParameter3", "Value3") }; var invocationParameters = new List { new("@SomeParameter1", "Value1"), new("@SomeParameter2", "Value2") }; var expectedResult = Fixture.CreateMany().ToList(); AddFromSqlRawResult(DbSet, sql, setUpParameters, expectedResult); Assert.Throws(() => { var actualResult1 = DbSet.FromSqlRaw("[dbo].[sp_WithParams] @SomeParameter1 @SomeParameter2", invocationParameters.ToArray()).ToList(); }); Assert.Throws(() => { var actualResult2 = DbSet.FromSqlRaw("sp_WithParams @SomeParameter1 @SomeParameter2", invocationParameters.ToArray()).ToList(); }); } [Test] public virtual void FromSqlRaw_SpecifiedSqlWithStringParameters_ReturnsExpectedResult() { var sql = "sp_WithParams"; var parameters = new List { "Value2" }; var expectedResult = Fixture.CreateMany().ToList(); AddFromSqlRawResult(DbSet, sql, parameters, expectedResult); var actualResult1 = DbSet.FromSqlRaw("[dbo].[sp_WithParams] @SomeParameter1 @SomeParameter2", parameters.ToArray()).ToList(); var actualResult2 = DbSet.FromSqlRaw("sp_WithParams @SomeParameter1 @SomeParameter2", parameters.ToArray()).ToList(); Assert.Multiple(() => { Assert.That(actualResult1, Is.EquivalentTo(expectedResult)); Assert.That(actualResult2, Is.EquivalentTo(actualResult1)); }); } [Test] public virtual void FromSqlRaw_ThrowsException() { Assert.Throws(() => { var actualResult = DbSet.FromSqlRaw("sp_NoParams").ToList(); }); } [Test] public virtual async Task FromSqlRawThenFirstOrDefaultAsync_ReturnsFirstElement() { var sql = "sp_NoParams"; var expectedResult = Fixture.CreateMany().ToList(); AddFromSqlRawResult(DbSet, sql, expectedResult); var actualResult1 = await DbSet.FromSqlRaw("[dbo].[sp_NoParams]").FirstOrDefaultAsync(); var actualResult2 = await DbSet.FromSqlRaw("[dbo].[sp_NoParams]").FirstOrDefaultAsync(); Assert.Multiple(() => { Assert.That(actualResult1, Is.EqualTo(expectedResult.First())); Assert.That(actualResult2, Is.EqualTo(expectedResult.First())); }); } [Test] public void ContainsListCollection_ReturnsFalse() { var containsListCollection = ((IListSource) Queryable).ContainsListCollection; Assert.That(containsListCollection, Is.False); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Common.Tests/BaseForQueryableTests.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using AutoFixture; using AutoMapper; using KellermanSoftware.CompareNetObjects; using Microsoft.EntityFrameworkCore; using NUnit.Framework; namespace EntityFrameworkCore.Testing.Common.Tests { public abstract class BaseForQueryableTests : BaseForTests where T : BaseTestEntity { protected List ItemsAddedToQueryableSource; protected abstract IQueryable Queryable { get; } protected abstract void SeedQueryableSource(); [Test] public virtual void All_FalseCondition_ReturnsFalse() { SeedQueryableSource(); var actualResult1 = Queryable.All(x => string.IsNullOrWhiteSpace(x.FullName)); var actualResult2 = Queryable.All(x => string.IsNullOrWhiteSpace(x.FullName)); Assert.Multiple(() => { Assert.That(actualResult1, Is.False); Assert.That(actualResult2, Is.False); }); } [Test] public virtual void All_TrueCondition_ReturnsTrue() { SeedQueryableSource(); var actualResult1 = Queryable.All(x => !string.IsNullOrWhiteSpace(x.FullName)); var actualResult2 = Queryable.All(x => !string.IsNullOrWhiteSpace(x.FullName)); Assert.Multiple(() => { Assert.That(actualResult1, Is.True); Assert.That(actualResult2, Is.True); }); } [Test] public virtual async Task AllAsync_FalseCondition_ReturnsFalse() { SeedQueryableSource(); var actualResult1 = await Queryable.AllAsync(x => string.IsNullOrWhiteSpace(x.FullName)); var actualResult2 = await Queryable.AllAsync(x => string.IsNullOrWhiteSpace(x.FullName)); Assert.Multiple(() => { Assert.That(actualResult1, Is.False); Assert.That(actualResult2, Is.False); }); } [Test] public virtual async Task AllAsync_TrueCondition_ReturnsTrue() { SeedQueryableSource(); var actualResult1 = await Queryable.AllAsync(x => !string.IsNullOrWhiteSpace(x.FullName)); var actualResult2 = await Queryable.AllAsync(x => !string.IsNullOrWhiteSpace(x.FullName)); Assert.Multiple(() => { Assert.That(actualResult1, Is.True); Assert.That(actualResult2, Is.True); }); } [Test] public virtual void Any_ReturnsTrue() { SeedQueryableSource(); var actualResult1 = Queryable.Any(); var actualResult2 = Queryable.Any(); Assert.Multiple(() => { Assert.That(actualResult1, Is.True); Assert.That(actualResult2, Is.True); }); } [Test] public virtual void Any_WithNoItemsAdded_ReturnsFalse() { var actualResult1 = Queryable.Any(); var actualResult2 = Queryable.Any(); Assert.Multiple(() => { Assert.That(actualResult1, Is.False); Assert.That(actualResult2, Is.False); }); } [Test] public virtual async Task AnyAsync_ReturnsTrue() { SeedQueryableSource(); var actualResult1 = await Queryable.AnyAsync(); var actualResult2 = await Queryable.AnyAsync(); Assert.Multiple(() => { Assert.That(actualResult1, Is.True); Assert.That(actualResult2, Is.True); }); } [Test] public virtual async Task AnyAsyncWithCancellationToken_ReturnsTrue() { SeedQueryableSource(); using (var cancellationTokenSource = new CancellationTokenSource(new TimeSpan(0, 1, 0))) { var actualResult1 = await Queryable.AnyAsync(cancellationTokenSource.Token); var actualResult2 = await Queryable.AnyAsync(cancellationTokenSource.Token); Assert.Multiple(() => { Assert.That(actualResult1, Is.True); Assert.That(actualResult2, Is.True); }); } } [Test] public virtual void Average_Decimal_ReturnsAverage() { SeedQueryableSource(); var actualResult1 = Queryable.Average(x => x.Weight); var actualResult2 = Queryable.Average(x => x.Weight); Assert.Multiple(() => { var average = 0m; for (var i = 0; i < ItemsAddedToQueryableSource.Count; i++) { average += ItemsAddedToQueryableSource[i].Weight; } average = average / ItemsAddedToQueryableSource.Count; Assert.That(actualResult1, Is.EqualTo(average)); Assert.That(actualResult2, Is.EqualTo(average)); }); } [Test] public virtual async Task AverageAsync_Decimal_ReturnsAverage() { SeedQueryableSource(); var actualResult1 = await Queryable.AverageAsync(x => x.Weight); var actualResult2 = await Queryable.AverageAsync(x => x.Weight); Assert.Multiple(() => { var average = 0m; for (var i = 0; i < ItemsAddedToQueryableSource.Count; i++) { average += ItemsAddedToQueryableSource[i].Weight; } average = average / ItemsAddedToQueryableSource.Count; Assert.That(actualResult1, Is.EqualTo(average)); Assert.That(actualResult2, Is.EqualTo(average)); }); } [Test] public virtual void Contains_FalseCondition_ReturnsFalse() { SeedQueryableSource(); var itemToFind = Fixture.Create(); var actualResult1 = Queryable.Contains(itemToFind); var actualResult2 = Queryable.Contains(itemToFind); Assert.Multiple(() => { Assert.That(actualResult1, Is.False); Assert.That(actualResult2, Is.False); }); } [Test] public virtual void Contains_TrueCondition_ReturnsTrue() { SeedQueryableSource(); var itemToFind = Queryable.First(); var actualResult1 = Queryable.Contains(itemToFind); var actualResult2 = Queryable.Contains(itemToFind); Assert.Multiple(() => { Assert.That(actualResult1, Is.True); Assert.That(actualResult2, Is.True); }); } [Test] public virtual async Task ContainsAsync_FalseCondition_ReturnsFalse() { SeedQueryableSource(); var itemToFind = Fixture.Create(); var actualResult1 = await Queryable.ContainsAsync(itemToFind); var actualResult2 = await Queryable.ContainsAsync(itemToFind); Assert.Multiple(() => { Assert.That(actualResult1, Is.False); Assert.That(actualResult2, Is.False); }); } [Test] public virtual async Task ContainsAsync_TrueCondition_ReturnsTrue() { SeedQueryableSource(); var itemToFind = Queryable.First(); var actualResult1 = await Queryable.ContainsAsync(itemToFind); var actualResult2 = await Queryable.ContainsAsync(itemToFind); Assert.Multiple(() => { Assert.That(actualResult1, Is.True); Assert.That(actualResult2, Is.True); }); } [Test] public virtual void ElementAt_ThrowsException() { SeedQueryableSource(); Assert.Multiple(() => { var ex1 = Assert.Throws(() => { var firstElement = Queryable.ElementAt(0); }); //Assert.That(ex1.Message, Is.EqualTo(string.Format(ExceptionMessages.TranslationFailedExceptionMessage, $"DbSet<{typeof(T).Name}>()\r\n .ElementAt(0)"))); var ex2 = Assert.Throws(() => { var lastElement = Queryable.ElementAt(Queryable.ToList().Count - 1); }); //Assert.That(ex2.Message, Is.EqualTo(string.Format(ExceptionMessages.TranslationFailedExceptionMessage, $"DbSet<{typeof(T).Name}>()\r\n .ElementAt({Queryable.ToList().Count - 1})"))); }); } [Test] public virtual void ElementAt_AfterAsEnumerable_DoesNotThrowException() { SeedQueryableSource(); Console.WriteLine("Assert start"); Assert.Multiple(() => { Assert.DoesNotThrow(() => { var firstElement = Queryable.AsEnumerable().ElementAt(0); }); Assert.DoesNotThrow(() => { var lastElement = Queryable.AsEnumerable().ElementAt(Queryable.ToList().Count - 1); }); }); } [Test] public virtual void ElementAt_AfterToList_DoesNotThrowException() { SeedQueryableSource(); Assert.Multiple(() => { Assert.DoesNotThrow(() => { var firstElement = Queryable.ToList().ElementAt(0); }); Assert.DoesNotThrow(() => { var lastElement = Queryable.ToList().ElementAt(Queryable.ToList().Count - 1); }); }); } [Test] public virtual void ElementAtOrDefault_ThrowsException() { SeedQueryableSource(); Assert.Multiple(() => { var ex1 = Assert.Throws(() => { var firstElement = Queryable.ElementAtOrDefault(0); }); //Assert.That(ex1.Message, Is.EqualTo(string.Format(ExceptionMessages.TranslationFailedExceptionMessage, $"DbSet<{typeof(T).Name}>()\r\n .ElementAtOrDefault(0)"))); var ex2 = Assert.Throws(() => { var lastElement = Queryable.ElementAtOrDefault(Queryable.ToList().Count - 1); }); //Assert.That(ex2.Message, Is.EqualTo(string.Format(ExceptionMessages.TranslationFailedExceptionMessage, $"DbSet<{typeof(T).Name}>()\r\n .ElementAtOrDefault({Queryable.ToList().Count - 1})"))); }); } [Test] public virtual void ElementAtOrDefault_WithNoItemsAdded_ThrowsException() { Assert.Multiple(() => { var ex1 = Assert.Throws(() => { var firstElement = Queryable.ElementAtOrDefault(0); }); //Assert.That(ex1.Message, Is.EqualTo(string.Format(ExceptionMessages.TranslationFailedExceptionMessage, $"DbSet<{typeof(T).Name}>()\r\n .ElementAtOrDefault(0)"))); var ex2 = Assert.Throws(() => { var lastElement = Queryable.ElementAtOrDefault(Queryable.ToList().Count - 1); }); //Assert.That(ex2.Message, Is.EqualTo(string.Format(ExceptionMessages.TranslationFailedExceptionMessage, $"DbSet<{typeof(T).Name}>()\r\n .ElementAtOrDefault({Queryable.ToList().Count - 1})"))); }); } [Test] public virtual void First_ReturnsFirstElement() { SeedQueryableSource(); var actualResult1 = Queryable.First(); var actualResult2 = Queryable.First(); Assert.Multiple(() => { Assert.That(actualResult1, Is.EqualTo(ItemsAddedToQueryableSource.First())); Assert.That(actualResult2, Is.EqualTo(ItemsAddedToQueryableSource.First())); }); } [Test] public virtual void First_WithNoItemsAdded_ThrowsException() { Assert.Throws(() => { var actualResult1 = Queryable.First(); }); } [Test] public virtual async Task FirstAsync_ReturnsFirstElement() { SeedQueryableSource(); var actualResult1 = await Queryable.FirstAsync(); var actualResult2 = await Queryable.FirstAsync(); Assert.Multiple(() => { Assert.That(actualResult1, Is.EqualTo(ItemsAddedToQueryableSource.First())); Assert.That(actualResult2, Is.EqualTo(ItemsAddedToQueryableSource.First())); }); } [Test] public virtual void FirstOrDefault_ReturnsFirstElement() { SeedQueryableSource(); var actualResult1 = Queryable.FirstOrDefault(); var actualResult2 = Queryable.FirstOrDefault(); Assert.Multiple(() => { Assert.That(actualResult1, Is.EqualTo(ItemsAddedToQueryableSource.First())); Assert.That(actualResult2, Is.EqualTo(ItemsAddedToQueryableSource.First())); }); } [Test] public virtual void FirstOrDefault_WithNoItemsAdded_ReturnsFirstElement() { var actualResult1 = Queryable.FirstOrDefault(); var actualResult2 = Queryable.FirstOrDefault(); Assert.Multiple(() => { Assert.That(actualResult1, Is.EqualTo(default(T))); Assert.That(actualResult2, Is.EqualTo(default(T))); }); } [Test] public virtual async Task FirstOrDefaultAsync_ReturnsFirstElement() { SeedQueryableSource(); var actualResult1 = await Queryable.FirstOrDefaultAsync(); var actualResult2 = await Queryable.FirstOrDefaultAsync(); Assert.Multiple(() => { Assert.That(actualResult1, Is.EqualTo(ItemsAddedToQueryableSource.First())); Assert.That(actualResult2, Is.EqualTo(ItemsAddedToQueryableSource.First())); }); } [Test] public virtual void Last_ReturnsLastElement() { SeedQueryableSource(); var actualResult1 = Queryable.Last(); var actualResult2 = Queryable.Last(); Assert.Multiple(() => { Assert.That(actualResult1, Is.EqualTo(ItemsAddedToQueryableSource.Last())); Assert.That(actualResult2, Is.EqualTo(ItemsAddedToQueryableSource.Last())); }); } [Test] public virtual void Last_WithNoItemsAdded_ThrowsException() { Assert.Throws(() => { var actualResult1 = Queryable.Last(); }); } [Test] public virtual async Task LastAsync_ReturnsLastElement() { SeedQueryableSource(); var actualResult1 = await Queryable.LastAsync(); var actualResult2 = await Queryable.LastAsync(); Assert.Multiple(() => { Assert.That(actualResult1, Is.EqualTo(ItemsAddedToQueryableSource.Last())); Assert.That(actualResult2, Is.EqualTo(ItemsAddedToQueryableSource.Last())); }); } [Test] public virtual void LastOrDefault_ReturnsLastElement() { SeedQueryableSource(); var actualResult1 = Queryable.LastOrDefault(); var actualResult2 = Queryable.LastOrDefault(); Assert.Multiple(() => { Assert.That(actualResult1, Is.EqualTo(ItemsAddedToQueryableSource.Last())); Assert.That(actualResult2, Is.EqualTo(ItemsAddedToQueryableSource.Last())); }); } [Test] public virtual void LastOrDefault_WithNoItemsAdded_ReturnsLastElement() { var actualResult1 = Queryable.LastOrDefault(); var actualResult2 = Queryable.LastOrDefault(); Assert.Multiple(() => { Assert.That(actualResult1, Is.EqualTo(default(T))); Assert.That(actualResult2, Is.EqualTo(default(T))); }); } [Test] public virtual async Task LastOrDefaultAsync_ReturnsLastElement() { SeedQueryableSource(); var actualResult1 = await Queryable.LastOrDefaultAsync(); var actualResult2 = await Queryable.LastOrDefaultAsync(); Assert.Multiple(() => { Assert.That(actualResult1, Is.EqualTo(ItemsAddedToQueryableSource.Last())); Assert.That(actualResult2, Is.EqualTo(ItemsAddedToQueryableSource.Last())); }); } [Test] public virtual void Max_DateTime_ReturnsMaxDateTime() { SeedQueryableSource(); var actualResult1 = Queryable.Max(x => x.DateOfBirth); var actualResult2 = Queryable.Max(x => x.DateOfBirth); Assert.Multiple(() => { var maxDateTime = ItemsAddedToQueryableSource[0].DateOfBirth; for (var i = 1; i < ItemsAddedToQueryableSource.Count; i++) { if (ItemsAddedToQueryableSource[i].DateOfBirth > maxDateTime) { maxDateTime = ItemsAddedToQueryableSource[i].DateOfBirth; } } Assert.That(actualResult1, Is.EqualTo(maxDateTime)); Assert.That(actualResult2, Is.EqualTo(maxDateTime)); }); } [Test] public virtual async Task MaxAsync_DateTime_ReturnsMaxDateTime() { SeedQueryableSource(); var actualResult1 = await Queryable.MaxAsync(x => x.DateOfBirth); var actualResult2 = await Queryable.MaxAsync(x => x.DateOfBirth); Assert.Multiple(() => { var maxDateTime = ItemsAddedToQueryableSource[0].DateOfBirth; for (var i = 1; i < ItemsAddedToQueryableSource.Count; i++) { if (ItemsAddedToQueryableSource[i].DateOfBirth > maxDateTime) { maxDateTime = ItemsAddedToQueryableSource[i].DateOfBirth; } } Assert.That(actualResult1, Is.EqualTo(maxDateTime)); Assert.That(actualResult2, Is.EqualTo(maxDateTime)); }); } [Test] public virtual void Min_DateTime_ReturnsMinDateTime() { SeedQueryableSource(); var actualResult1 = Queryable.Min(x => x.DateOfBirth); var actualResult2 = Queryable.Min(x => x.DateOfBirth); Assert.Multiple(() => { var minDateTime = ItemsAddedToQueryableSource[0].DateOfBirth; for (var i = 1; i < ItemsAddedToQueryableSource.Count; i++) { if (ItemsAddedToQueryableSource[i].DateOfBirth < minDateTime) { minDateTime = ItemsAddedToQueryableSource[i].DateOfBirth; } } Assert.That(actualResult1, Is.EqualTo(minDateTime)); Assert.That(actualResult2, Is.EqualTo(minDateTime)); }); } [Test] public virtual async Task MinAsync_DateTime_ReturnsMinDateTime() { SeedQueryableSource(); var actualResult1 = await Queryable.MinAsync(x => x.DateOfBirth); var actualResult2 = await Queryable.MinAsync(x => x.DateOfBirth); Assert.Multiple(() => { var minDateTime = ItemsAddedToQueryableSource[0].DateOfBirth; for (var i = 1; i < ItemsAddedToQueryableSource.Count; i++) { if (ItemsAddedToQueryableSource[i].DateOfBirth < minDateTime) { minDateTime = ItemsAddedToQueryableSource[i].DateOfBirth; } } Assert.That(actualResult1, Is.EqualTo(minDateTime)); Assert.That(actualResult2, Is.EqualTo(minDateTime)); }); } [Test] public virtual void OrderBy_DateTime_ReturnsItemsInAscendingOrder() { SeedQueryableSource(); var actualResult1 = Queryable.OrderBy(x => x.DateOfBirth).ToList(); var actualResult2 = Queryable.OrderBy(x => x.DateOfBirth).ToList(); Assert.Multiple(() => { for (var i = 1; i < actualResult1.Count; i++) { Assert.That(actualResult1[i].DateOfBirth, Is.GreaterThanOrEqualTo(actualResult1[i - 1].DateOfBirth)); } for (var i = 1; i < actualResult2.Count; i++) { Assert.That(actualResult2[i].DateOfBirth, Is.GreaterThanOrEqualTo(actualResult2[i - 1].DateOfBirth)); } }); } [Test] public virtual void OrderByDescending_DateTime_ReturnsItemsInDescendingOrder() { SeedQueryableSource(); var actualResult1 = Queryable.OrderByDescending(x => x.DateOfBirth).ToList(); var actualResult2 = Queryable.OrderByDescending(x => x.DateOfBirth).ToList(); Assert.Multiple(() => { for (var i = 1; i < actualResult1.Count; i++) { Assert.That(actualResult1[i].DateOfBirth, Is.LessThanOrEqualTo(actualResult1[i - 1].DateOfBirth)); } for (var i = 1; i < actualResult2.Count; i++) { Assert.That(actualResult2[i].DateOfBirth, Is.LessThanOrEqualTo(actualResult2[i - 1].DateOfBirth)); } }); } [Test] public virtual void OrderByThenOrderBy_FixedDateTimeAndDecimal_ReturnsItemsInAscendingOrder() { SeedQueryableSource(); var actualResult1 = Queryable.OrderBy(x => x.CreatedAt).ThenBy(x => x.Weight).ToList(); var actualResult2 = Queryable.OrderBy(x => x.CreatedAt).ThenBy(x => x.Weight).ToList(); Assert.Multiple(() => { for (var i = 1; i < actualResult1.Count; i++) { Assert.That(actualResult1[i].Weight, Is.GreaterThanOrEqualTo(actualResult1[i - 1].Weight)); } for (var i = 1; i < actualResult2.Count; i++) { Assert.That(actualResult2[i].Weight, Is.GreaterThanOrEqualTo(actualResult2[i - 1].Weight)); } }); } [Test] public virtual void Select_ReturnsSequence() { SeedQueryableSource(); var actualResult1 = Queryable.Select(x => x).ToList(); var actualResult2 = Queryable.Select(x => x).ToList(); Assert.Multiple(() => { for (var i = 0; i < ItemsAddedToQueryableSource.Count; i++) { Assert.That(actualResult1[i], Is.EqualTo(ItemsAddedToQueryableSource[i])); Assert.That(actualResult2[i], Is.EqualTo(ItemsAddedToQueryableSource[i])); } }); } [Test] public virtual async Task SelectAnonymousObjectThenToListAsync_ReturnsList() { SeedQueryableSource(); var expectedResult = Queryable.Select(x => new { x.Id }).ToList(); var actualResult1 = await Queryable.Select(x => new { x.Id }).ToListAsync(); var actualResult2 = await Queryable.Select(x => new { x.Id }).ToListAsync(); Assert.Multiple(() => { Assert.That(actualResult1, Is.EquivalentTo(expectedResult)); Assert.That(actualResult2, Is.EquivalentTo(expectedResult)); }); } [Test] public virtual void SelectWithIndex_ThrowsException() { SeedQueryableSource(); Assert.Multiple(() => { var ex1 = Assert.Throws(() => { var actualResult1 = Queryable.Select((x, i) => new { Index = i, Item = x }).ToList(); }); //Assert.That(ex1.Message, Is.EqualTo(string.Format(ExceptionMessages.TranslationFailedExceptionMessage, typeof(T).Name))); var ex2 = Assert.Throws(() => { var actualResult2 = Queryable.Select((x, i) => new { Index = i, Item = x }).ToList(); }); //Assert.That(ex2.Message, Is.EqualTo(string.Format(ExceptionMessages.TranslationFailedExceptionMessage, typeof(T).Name))); }); } [Test] public virtual void SelectWithIndexThenWhereThenAny_TrueCondition_ThrowsException() { SeedQueryableSource(); Assert.Multiple(() => { var ex = Assert.Throws(() => { var actualResult1 = Queryable.Select((x, i) => new { Index = i, Item = x }).Where(x => !x.Index.Equals(0)).Any(); }); //Assert.That(ex.Message, Is.EqualTo(string.Format(ExceptionMessages.TranslationFailedExceptionMessage, typeof(T).Name))); }); } [Test] public virtual void Skip_One_ReturnsSequenceThatDoesNotIncludeFirstItem() { SeedQueryableSource(); var firstItem = Queryable.First(); var actualResult1 = Queryable.Skip(1); var actualResult2 = Queryable.Skip(1); Assert.Multiple(() => { Assert.That(actualResult1.Contains(firstItem), Is.False); Assert.That(actualResult1.Count(), Is.EqualTo(Queryable.Count() - 1)); Assert.That(actualResult2.Contains(firstItem), Is.False); Assert.That(actualResult2.Count(), Is.EqualTo(Queryable.Count() - 1)); }); } [Test] public virtual void SkipWhile_SkipFirstItem_ThrowsException() { SeedQueryableSource(); var firstItem = Queryable.First(); Assert.Multiple(() => { var ex1 = Assert.Throws(() => { var actualResult1 = Queryable.SkipWhile(x => x.Equals(firstItem)).ToList(); }); //Assert.That(ex1.Message, Is.EqualTo(string.Format(ExceptionMessages.TranslationFailedExceptionMessage, typeof(T).Name))); var ex2 = Assert.Throws(() => { var actualResult2 = Queryable.SkipWhile(x => x.Equals(firstItem)).ToList(); }); //Assert.That(ex2.Message, Is.EqualTo(string.Format(ExceptionMessages.TranslationFailedExceptionMessage, typeof(T).Name))); }); } [Test] public virtual void Take_One_ReturnsFirstItem() { SeedQueryableSource(); var firstItem = Queryable.First(); var actualResult1 = Queryable.Take(1); var actualResult2 = Queryable.Take(1); Assert.Multiple(() => { Assert.That(actualResult1.Count(), Is.EqualTo(1)); Assert.That(actualResult1.First(), Is.EqualTo(firstItem)); Assert.That(actualResult2.Count(), Is.EqualTo(1)); Assert.That(actualResult2.First(), Is.EqualTo(firstItem)); }); } [Test] public virtual void TakeWhile_TakeFirstItem_ThrowsException() { SeedQueryableSource(); var firstItem = Queryable.First(); Assert.Multiple(() => { var ex1 = Assert.Throws(() => { var actualResult1 = Queryable.TakeWhile(x => x.Equals(firstItem)).ToList(); }); //Assert.That(ex1.Message, Is.EqualTo(string.Format(ExceptionMessages.TranslationFailedExceptionMessage, typeof(T).Name))); var ex2 = Assert.Throws(() => { var actualResult2 = Queryable.TakeWhile(x => x.Equals(firstItem)).ToList(); }); //Assert.That(ex2.Message, Is.EqualTo(string.Format(ExceptionMessages.TranslationFailedExceptionMessage, typeof(T).Name))); }); } [Test] public virtual void TakeWhile_TakeFirstItemUsingIndex_ThrowsException() { SeedQueryableSource(); Assert.Multiple(() => { var ex1 = Assert.Throws(() => { var actualResult1 = Queryable.TakeWhile((x, i) => i.Equals(0)).ToList(); }); //Assert.That(ex1.Message, Is.EqualTo(string.Format(ExceptionMessages.TranslationFailedExceptionMessage, typeof(T).Name))); var ex2 = Assert.Throws(() => { var actualResult2 = Queryable.TakeWhile((x, i) => i.Equals(0)).ToList(); }); //Assert.That(ex2.Message, Is.EqualTo(string.Format(ExceptionMessages.TranslationFailedExceptionMessage, typeof(T).Name))); }); } [Test] public virtual async Task ToListAsync_ReturnsList() { SeedQueryableSource(); var expectedResult = Queryable.ToList(); var actualResult1 = await Queryable.ToListAsync(); var actualResult2 = await Queryable.ToListAsync(); Assert.Multiple(() => { Assert.That(actualResult1, Is.EquivalentTo(expectedResult)); Assert.That(actualResult2, Is.EquivalentTo(expectedResult)); }); } [Test] public virtual void Where_Condition_ReturnsItemsThatSatisfyCondition() { SeedQueryableSource(); var actualResult1 = Queryable.Where(x => !x.Id.Equals(default)).ToList(); var actualResult2 = Queryable.Where(x => !x.Id.Equals(default)).ToList(); Assert.Multiple(() => { for (var i = 0; i < ItemsAddedToQueryableSource.Count; i++) { var item = ItemsAddedToQueryableSource[i]; Assert.That(item.Id, Is.Not.EqualTo(default(Guid))); Assert.That(actualResult1[i], Is.EqualTo(item)); Assert.That(actualResult1[i].Id, Is.Not.EqualTo(default(Guid))); Assert.That(actualResult2[i], Is.EqualTo(item)); Assert.That(actualResult2[i].Id, Is.Not.EqualTo(default(Guid))); } }); } [Test] public async Task ProjectToThenToListAsync_ReturnsExpectedResult() { SeedQueryableSource(); var expectedResult = new AsyncEnumerable(Queryable.Select(x => new TestViewModel { id = x.Id, fullName = x.FullName })); var mapper = new Mapper(new MapperConfiguration(x => x.AddProfile(new MappingProfile()))); Console.WriteLine("ProjectTo about to be invoked"); var actualResult = await mapper.ProjectTo(Queryable, null).ToListAsync(); var compareLogic = new CompareLogic { Config = { IgnoreObjectTypes = true, IgnoreCollectionOrder = true } }; var comparisonResult = compareLogic.Compare(expectedResult, actualResult); Assert.That(comparisonResult.AreEqual, Is.True); } [Test] public virtual void ToListThenElementAt_Zero_ReturnsFirstElement() { SeedQueryableSource(); var firstElement = Queryable.ToList().ElementAt(0); Assert.That(firstElement, Is.EqualTo(ItemsAddedToQueryableSource.First())); } [Test] public virtual void WhereWithSelect_Condition_ReturnsIdsThatSatisfyCondition() { SeedQueryableSource(); var actualResult1 = Queryable.Where(x => !x.Id.Equals(default)).Select(x => x.Id).ToList(); var actualResult2 = Queryable.Where(x => !x.Id.Equals(default)).Select(x => x.Id).ToList(); Assert.Multiple(() => { for (var i = 0; i < ItemsAddedToQueryableSource.Count; i++) { var item = ItemsAddedToQueryableSource[i]; Assert.That(item.Id, Is.Not.EqualTo(default(Guid))); Assert.That(actualResult1[i], Is.EqualTo(item.Id)); Assert.That(actualResult1[i], Is.Not.EqualTo(default(Guid))); Assert.That(actualResult2[i], Is.EqualTo(item.Id)); Assert.That(actualResult2[i], Is.Not.EqualTo(default(Guid))); } }); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Common.Tests/BaseForReadOnlyDbSetTests.cs ================================================ using System; using System.Collections.Generic; using Microsoft.Data.SqlClient; using System.Linq; using System.Threading.Tasks; using AutoFixture; using Microsoft.EntityFrameworkCore; using NUnit.Framework; namespace EntityFrameworkCore.Testing.Common.Tests { public abstract class BaseForReadOnlyDbSetTests : BaseForMockedQueryableTests where TEntity : BaseTestEntity { protected override void SeedQueryableSource() { var itemsToAdd = Fixture.Build().With(p => p.CreatedAt, DateTime.Today).With(p => p.LastModifiedAt, DateTime.Today).CreateMany().ToList(); AddRangeToReadOnlySource(DbSet, itemsToAdd); //MockedDbContext.SaveChanges(); ItemsAddedToQueryableSource = itemsToAdd; } protected abstract void AddToReadOnlySource(DbSet mockedDbQuery, TEntity item); protected abstract void AddRangeToReadOnlySource(DbSet mockedDbQuery, IEnumerable items); protected abstract void ClearReadOnlySource(DbSet mockedDbQuery); [Test] public virtual void AddRangeToReadOnlySource_Items_AddsItemsToReadOnlySource() { var expectedResult = Fixture.CreateMany().ToList(); AddRangeToReadOnlySource(DbSet, expectedResult); Assert.That(DbSet, Is.EquivalentTo(expectedResult)); } [Test] public virtual void AddRangeToReadOnlySourceThenAddRangeToReadOnlySource_Items_AddsAllItemsToReadOnlySource() { var expectedResult = Fixture.CreateMany(4).ToList(); AddRangeToReadOnlySource(DbSet, expectedResult.Take(2)); AddRangeToReadOnlySource(DbSet, expectedResult.Skip(2)); Assert.That(DbSet, Is.EquivalentTo(expectedResult)); } [Test] public virtual void AddToReadOnlySource_Item_AddsItemToReadOnlySource() { var expectedResult = Fixture.Create(); AddToReadOnlySource(DbSet, expectedResult); var numberOfItemsAdded = DbSet.ToList().Count; Assert.That(numberOfItemsAdded, Is.EqualTo(1)); } [Test] public virtual void AddToReadOnlySourceThenAddToReadOnlySource_Items_AddsBothItemsToReadOnlySource() { var expectedResult = Fixture.CreateMany(2).ToList(); AddToReadOnlySource(DbSet, expectedResult.First()); AddToReadOnlySource(DbSet, expectedResult.Last()); Assert.That(DbSet, Is.EquivalentTo(expectedResult)); } [Test] public virtual void AnyThenAddToReadOnlySourceThenAny_ReturnsFalseThenTrue() { var actualResult1 = DbSet.Any(); AddToReadOnlySource(DbSet, Fixture.Create()); var actualResult2 = DbSet.Any(); Assert.Multiple(() => { Assert.That(actualResult1, Is.False); Assert.That(actualResult2, Is.True); }); } [Test] public virtual async Task AsAsyncEnumerable_ReturnsAsyncEnumerable() { var expectedResult = Fixture.Create(); AddToReadOnlySource(DbSet, expectedResult); var asyncEnumerable = DbSet.AsAsyncEnumerable(); var actualResults = new List(); await foreach (var item in asyncEnumerable) { actualResults.Add(item); } Assert.Multiple(() => { Assert.That(actualResults.Single(), Is.EqualTo(expectedResult)); Assert.That(actualResults.Single(), Is.EqualTo(expectedResult)); }); } [Test] public virtual void AsQueryable_ReturnsQueryable() { var expectedResult = Fixture.Create(); AddToReadOnlySource(DbSet, expectedResult); var queryable = DbSet.AsQueryable(); Assert.Multiple(() => { Assert.That(queryable.Single(), Is.EqualTo(expectedResult)); Assert.That(queryable.Single(), Is.EqualTo(expectedResult)); }); } [Test] public virtual void ClearReadOnlySource_WithNoItemsAddedToReadOnlySource_DoesNothing() { var preActNumberOfItems = DbSet.ToList().Count; ClearReadOnlySource(DbSet); var postActNumberOfItems = DbSet.ToList().Count; Assert.Multiple(() => { Assert.That(preActNumberOfItems, Is.EqualTo(0)); Assert.That(postActNumberOfItems, Is.EqualTo(preActNumberOfItems)); }); } [Test] public virtual void ClearReadOnlySourceWithExistingItems_RemovesAllItemsFromReadOnlySource() { var expectedResult = Fixture.CreateMany().ToList(); AddRangeToReadOnlySource(DbSet, expectedResult); var numberOfItemsAdded = DbSet.ToList().Count; ClearReadOnlySource(DbSet); Assert.Multiple(() => { Assert.That(numberOfItemsAdded, Is.EqualTo(expectedResult.Count)); Assert.That(DbSet.Any(), Is.False); }); } [Test] public override void FromSqlRaw_QueryProviderWithManyFromSqlResults_ReturnsExpectedResults() { var sql1 = "sp_NoParams"; var expectedResult1 = Fixture.CreateMany().ToList(); var sql2 = "sp_WithParams"; var parameters2 = new List { new("@SomeParameter1", "Value1"), new("@SomeParameter2", "Value2") }; var expectedResult2 = Fixture.CreateMany().ToList(); AddFromSqlRawResult(DbSet, sql1, expectedResult1); //Change the source, this will force the query provider mock to aggregate AddRangeToReadOnlySource(DbSet, Fixture.CreateMany().ToList()); AddFromSqlRawResult(DbSet, sql2, parameters2, expectedResult2); Console.WriteLine("actualResult1"); var actualResult1 = DbSet.FromSqlRaw("[dbo].[sp_NoParams]").ToList(); Console.WriteLine("actualResult2"); var actualResult2 = DbSet.FromSqlRaw("[dbo].[sp_WithParams]", parameters2.ToArray()).ToList(); Assert.Multiple(() => { Assert.That(actualResult1, Is.EquivalentTo(expectedResult1)); Assert.That(actualResult2, Is.EquivalentTo(expectedResult2)); }); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Common.Tests/BaseForTests.cs ================================================ using AutoFixture; using Microsoft.Extensions.Logging; using NUnit.Framework; using rgvlee.Core.Common.Helpers; namespace EntityFrameworkCore.Testing.Common.Tests { public abstract class BaseForTests { protected Fixture Fixture; [SetUp] public virtual void SetUp() { LoggingHelper.LoggerFactory = LoggerFactory.Create(builder => builder.AddConsole().SetMinimumLevel(LogLevel.Trace)); Fixture = new Fixture(); } [TearDown] public virtual void TearDown() { LoggingHelper.LoggerFactory.Dispose(); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Common.Tests/BaseTestEntity.cs ================================================ using System; namespace EntityFrameworkCore.Testing.Common.Tests { public abstract class BaseTestEntity { public Guid Id { get; set; } public string FullName { get; set; } public decimal Weight { get; set; } public decimal Height { get; set; } public DateTime DateOfBirth { get; set; } public DateTime CreatedAt { get; set; } public DateTime LastModifiedAt { get; set; } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Common.Tests/EntityFrameworkCore.Testing.Common.Tests.csproj ================================================ net10.0 false NU1605 true NU1605 runtime; build; native; contentfiles; analyzers; buildtransitive all all runtime; build; native; contentfiles; analyzers; buildtransitive all runtime; build; native; contentfiles; analyzers; buildtransitive ================================================ FILE: src/EntityFrameworkCore.Testing.Common.Tests/Issue114Tests.cs ================================================ using System.Linq; using FluentAssertions; using Microsoft.EntityFrameworkCore; using NUnit.Framework; namespace EntityFrameworkCore.Testing.Common.Tests { public abstract class Issue114Tests : BaseForTests { protected abstract TestDbContext MockedDbContextFactory(); [Test] public void Any_ForReadOnlyEntityWithNoDbContextProperty_IsFalse() { var mockedContext = MockedDbContextFactory(); mockedContext.Set().Any().Should().BeFalse(); } public class TestDbContext : DbContext { public TestDbContext(DbContextOptions options) : base(options) { } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity().HasNoKey(); } } public class Foo { public string Bar { get; set; } } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Common.Tests/Issue117Tests.cs ================================================ using System.Linq; using AutoFixture; using FluentAssertions; using Microsoft.EntityFrameworkCore; using NUnit.Framework; using static FluentAssertions.FluentActions; namespace EntityFrameworkCore.Testing.Common.Tests { public abstract class Issue117Tests : BaseForTests { protected abstract TestDbContext MockedDbContextFactory(); [Test] public void DbContextDispose_InvokedViaUsingBlock_DoesNotThrowException() { Invoking(() => { using (MockedDbContextFactory()) { } }).Should().NotThrow(); } [Test] public void DbContextDispose_DoesNotThrowException() { Invoking(() => MockedDbContextFactory().Dispose()).Should().NotThrow(); } [Test] public void DbContextAddRange_DoesNotThrowException() { Invoking(() => MockedDbContextFactory().AddRange(Fixture.CreateMany())).Should().NotThrow(); } [Test] public void DbContextAddRangeThenSaveChanges_WithinUsingBlock_PersistsMutableEntities() { using (var dbContext = MockedDbContextFactory()) { var entities = Fixture.CreateMany(); dbContext.AddRange(entities); dbContext.SaveChanges(); dbContext.Set().ToList().Should().BeEquivalentTo(entities); } } public class TestDbContext : DbContext { public TestDbContext(DbContextOptions options) : base(options) { } public virtual DbSet MutableEntities { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity().HasKey(c => c.Id); } } public class Foo { public string Id { get; set; } public string Bar { get; set; } } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Common.Tests/Issue126Tests.cs ================================================ using System; using System.Threading; using System.Threading.Tasks; using FluentAssertions; using Microsoft.EntityFrameworkCore; using NUnit.Framework; namespace EntityFrameworkCore.Testing.Common.Tests; public abstract class Issue126Tests : BaseForTests where TDbContext : DbContext { protected Func DbContextFactory; [Test] public virtual void BeginTransaction_ReturnsMockTransaction() { using var transaction = DbContextFactory().Database.BeginTransaction(); transaction.Should().NotBeNull(); } [TestCase(true)] [TestCase(false)] public virtual async Task BeginTransactionAsync_ReturnsMockTransaction(bool withCancellationTokenParameter) { await using var transaction = withCancellationTokenParameter ? await DbContextFactory().Database.BeginTransactionAsync(CancellationToken.None) : await DbContextFactory().Database.BeginTransactionAsync(); transaction.Should().NotBeNull(); } } ================================================ FILE: src/EntityFrameworkCore.Testing.Common.Tests/Issue49Tests.cs ================================================ using AutoFixture; using FluentAssertions; using Microsoft.EntityFrameworkCore; using NUnit.Framework; namespace EntityFrameworkCore.Testing.Common.Tests { public abstract class Issue49Tests : BaseForTests where TDbContext : DbContext where TEntity : BaseTestEntity { protected TDbContext DbContext; [Test] public virtual void EntityEntryState_Entity_IsDetached() { var entity = Fixture.Create(); var actualResult = DbContext.Entry(entity).State; actualResult.Should().Be(EntityState.Detached); } [Test] public virtual void EntityEntryState_EntityAsObject_IsDetached() { var entity = Fixture.Create(); var actualResult = DbContext.Entry((object) entity).State; actualResult.Should().Be(EntityState.Detached); } [Test] public virtual void DbContextAdd_Entity_IsAdded() { var entity = Fixture.Create(); var actualResult = DbContext.Add(entity); actualResult.State.Should().Be(EntityState.Added); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Common.Tests/Issue88Tests.cs ================================================ using System; using System.Linq; using AutoFixture; using FluentAssertions; using Microsoft.EntityFrameworkCore; using NUnit.Framework; namespace EntityFrameworkCore.Testing.Common.Tests { public abstract class Issue88Tests : BaseForTests where TDbContext : DbContext where TEntity : BaseTestEntity { protected Func DbContextFactory; [Test] public virtual void AddThenSaveChanges_ChangesVisibleAnyDbContext() { var entity = Fixture.Create(); var dbContext = DbContextFactory(); dbContext.Set().Add(entity); dbContext.SaveChanges(); dbContext.Find(entity.Id).Should().BeEquivalentTo(entity); dbContext.Set().Single(x => x.Id.Equals(entity.Id)).Should().BeEquivalentTo(entity); var anotherDbContext = DbContextFactory(); anotherDbContext.Find(entity.Id).Should().BeEquivalentTo(entity); anotherDbContext.Set().Single(x => x.Id.Equals(entity.Id)).Should().BeEquivalentTo(entity); } [Test] public virtual void BeginTransactionThenAddThenSaveChangesThenCommit_ChangesVisibleAnyDbContext() { var entity = Fixture.Create(); var dbContext = DbContextFactory(); using (var transaction = dbContext.Database.BeginTransaction()) { dbContext.Set().Add(entity); dbContext.SaveChanges(); transaction.Commit(); } dbContext.Find(entity.Id).Should().BeEquivalentTo(entity); dbContext.Set().Single(x => x.Id.Equals(entity.Id)).Should().BeEquivalentTo(entity); var anotherDbContext = DbContextFactory(); anotherDbContext.Find(entity.Id).Should().BeEquivalentTo(entity); anotherDbContext.Set().Single(x => x.Id.Equals(entity.Id)).Should().BeEquivalentTo(entity); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Common.Tests/MappingProfile.cs ================================================ using AutoMapper; namespace EntityFrameworkCore.Testing.Common.Tests { public class MappingProfile : Profile { public MappingProfile() { CreateMap(); CreateMap(); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Common.Tests/NotRegisteredEntity.cs ================================================ namespace EntityFrameworkCore.Testing.Common.Tests { public class NotRegisteredEntity : BaseTestEntity { } } ================================================ FILE: src/EntityFrameworkCore.Testing.Common.Tests/ReadOnlyDbSetExceptionTests.cs ================================================ using System; using AutoFixture; using Microsoft.EntityFrameworkCore; using NUnit.Framework; namespace EntityFrameworkCore.Testing.Common.Tests { public abstract class ReadOnlyDbSetExceptionTests : BaseForTests where TEntity : BaseTestEntity { protected abstract DbSet DbSet { get; } [Test] public void Add_Item_ThrowsException() { var ex = Assert.Throws(() => { DbSet.Add(Fixture.Create()); }); Assert.That(ex.Message, Is.EqualTo( $"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.")); } [Test] public void AddAsync_Item_ThrowsException() { var ex = Assert.ThrowsAsync(async () => { await DbSet.AddAsync(Fixture.Create()); }); Assert.That(ex.Message, Is.EqualTo( $"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.")); } [Test] public void AddRange_Items_ThrowsException() { var ex = Assert.Throws(() => { DbSet.AddRange(Fixture.CreateMany()); }); Assert.That(ex.Message, Is.EqualTo( $"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.")); } [Test] public void AddRangeAsync_Items_ThrowsException() { var ex = Assert.ThrowsAsync(async () => { await DbSet.AddRangeAsync(Fixture.CreateMany()); }); Assert.That(ex.Message, Is.EqualTo( $"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.")); } [Test] public void Attach_Item_ThrowsException() { var ex = Assert.Throws(() => { DbSet.Attach(Fixture.Create()); }); Assert.That(ex.Message, Is.EqualTo( $"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.")); } [Test] public void AttachRange_Items_ThrowsException() { var ex = Assert.Throws(() => { DbSet.AttachRange(Fixture.CreateMany()); }); Assert.That(ex.Message, Is.EqualTo( $"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.")); } [Test] public void Find_Item_ThrowsException() { var itemToFind = Fixture.Create(); var ex = Assert.Throws(() => { DbSet.Find(itemToFind.Id); }); 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.")); } [Test] public void Find_Items_ThrowsException() { var itemsToFind = Fixture.CreateMany(); var ex = Assert.ThrowsAsync(async () => { await DbSet.FindAsync(itemsToFind); }); 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.")); } [Test] public void Local_ThrowsException() { var ex = Assert.Throws(() => { var localView = DbSet.Local; }); 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.")); } [Test] public void Remove_Item_ThrowsException() { var ex = Assert.Throws(() => { DbSet.Remove(Fixture.Create()); }); Assert.That(ex.Message, Is.EqualTo( $"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.")); } [Test] public void RemoveRange_Items_ThrowsException() { var ex = Assert.Throws(() => { DbSet.RemoveRange(Fixture.CreateMany()); }); Assert.That(ex.Message, Is.EqualTo( $"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.")); } [Test] public void Update_Item_ThrowsException() { var ex = Assert.Throws(() => { DbSet.Update(Fixture.Create()); }); Assert.That(ex.Message, Is.EqualTo( $"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.")); } [Test] public void UpdateRange_Items_ThrowsException() { var ex = Assert.Throws(() => { DbSet.UpdateRange(Fixture.CreateMany()); }); Assert.That(ex.Message, Is.EqualTo( $"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.")); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Common.Tests/TestDbContext.cs ================================================ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using rgvlee.Core.Common.Helpers; namespace EntityFrameworkCore.Testing.Common.Tests { public class TestDbContext : DbContext { private static readonly ILogger Logger = LoggingHelper.CreateLogger(); public TestDbContext() { } public TestDbContext(DbContextOptions options) : base(options) { } public TestDbContext(ILogger logger, DbContextOptions options) : base(options) { } public virtual DbSet TestEntities { get; set; } public virtual DbSet TestReadOnlyEntities { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity().HasKey(c => c.Id); modelBuilder.Entity().HasNoKey().ToView("TestReadOnlyEntities"); } public override int SaveChanges() { Logger.LogDebug("SaveChanges invoked"); return base.SaveChanges(); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Common.Tests/TestEntity.cs ================================================ namespace EntityFrameworkCore.Testing.Common.Tests { public class TestEntity : BaseTestEntity { } } ================================================ FILE: src/EntityFrameworkCore.Testing.Common.Tests/TestReadOnlyEntity.cs ================================================ namespace EntityFrameworkCore.Testing.Common.Tests { public class TestReadOnlyEntity : BaseTestEntity { } } ================================================ FILE: src/EntityFrameworkCore.Testing.Common.Tests/TestViewModel.cs ================================================ using System; namespace EntityFrameworkCore.Testing.Common.Tests { public class TestViewModel { public Guid id { get; set; } public string fullName { get; set; } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Moq/Create.cs ================================================ using System.Linq; using EntityFrameworkCore.Testing.Moq.Extensions; using EntityFrameworkCore.Testing.Moq.Helpers; using Microsoft.EntityFrameworkCore; using rgvlee.Core.Common.Helpers; namespace EntityFrameworkCore.Testing.Moq { /// /// Factory for creating mocked instances. /// public static class Create { /// /// Creates a mocked db context. /// /// The db context type. /// /// The parameters that will be used to create the mocked db context and, if one is not provided, /// the in-memory context that the mocked db context will use for in-memory provider supported operations. /// /// A mocked db context. /// /// If you do not provide any constructor arguments this method attempt to create a TDbContext /// via a constructor with a single DbContextOptionsBuilder parameter or a parameterless constructor. /// public static TDbContext MockedDbContextFor(params object[] constructorParameters) where TDbContext : DbContext { return constructorParameters != null && constructorParameters.Any() ? new MockedDbContextBuilder().UseConstructorWithParameters(constructorParameters).MockedDbContext : new MockedDbContextBuilder().MockedDbContext; } /// /// Creates a mocked query provider. /// /// The queryable type. /// The query provider source. /// A mocked query provider. public static IQueryProvider MockedQueryProviderFor(IQueryable queryable) where T : class { EnsureArgument.IsNotNull(queryable, nameof(queryable)); return queryable.Provider.CreateMockedQueryProvider(queryable); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Moq/EntityFrameworkCore.Testing.Moq.csproj ================================================ net10.0 rgvlee EntityFrameworkCore.Testing.Moq.xml NU1605 EntityFrameworkCore.Testing.Moq.xml true NU1605 ================================================ FILE: src/EntityFrameworkCore.Testing.Moq/EntityFrameworkCore.Testing.Moq.xml ================================================ EntityFrameworkCore.Testing.Moq Factory for creating mocked instances. Creates a mocked db context. The db context type. The parameters that will be used to create the mocked db context and, if one is not provided, the in-memory context that the mocked db context will use for in-memory provider supported operations. A mocked db context. If you do not provide any constructor arguments this method attempt to create a TDbContext via a constructor with a single DbContextOptionsBuilder parameter or a parameterless constructor. Creates a mocked query provider. The queryable type. The query provider source. A mocked query provider. Extensions for db contexts. Sets up ExecuteSqlInterpolated invocations to return a specified result. The db context type. The mocked db context. The integer to return when ExecuteSqlInterpolated is invoked. Operations to perform after ExecuteSqlCommand is invoked. The mocked db context. Sets up ExecuteSqlInterpolated invocations containing a specified sql string to return a specified result. The db context type. The mocked db context. The ExecuteSqlInterpolated sql string. Set up supports case insensitive partial matches. The integer to return when ExecuteSqlInterpolated is invoked. Operations to perform after ExecuteSqlCommand is invoked. The mocked db context. Sets up ExecuteSqlInterpolated invocations containing a specified sql string to return a specified result. The db context type. The mocked db context. The ExecuteSqlInterpolated sql string. Set up supports case insensitive partial matches. The ExecuteSqlInterpolated parameters. Set up supports case insensitive partial parameter sequence matching. The integer to return when ExecuteSqlInterpolated is invoked. Operations to perform after ExecuteSqlCommand is invoked. The mocked db context. Sets up ExecuteSqlRaw invocations to return a specified result. The db context type. The mocked db context. The integer to return when ExecuteSqlRaw is invoked. Operations to perform after ExecuteSqlCommand is invoked. The mocked db context. Sets up ExecuteSqlRaw invocations containing a specified sql string and parameters to return a specified result. The db context type. The mocked db context. The ExecuteSqlRaw sql string. Set up supports case insensitive partial matches. The integer to return when ExecuteSqlRaw is invoked. Operations to perform after ExecuteSqlCommand is invoked. The mocked db context. Sets up ExecuteSqlRaw invocations containing a specified sql string and parameters to return a specified result. The db context type. The mocked db context. The ExecuteSqlRaw sql string. Set up supports case insensitive partial matches. The ExecuteSqlRaw parameters. Set up supports case insensitive partial parameter sequence matching. The integer to return when ExecuteSqlRaw is invoked. Operations to perform after ExecuteSqlCommand is invoked. The mocked db context. Extensions for db sets. Extensions for queryable collections. Sets up FromSqlInterpolated invocations to return a specified result. The queryable source type. The mocked queryable. The FromSqlInterpolated result. The mocked queryable. Sets up FromSqlInterpolated invocations to return a specified result. The queryable source type. The mocked queryable. The FromSqlInterpolated sql string. Set up supports case insensitive partial matches. The FromSqlInterpolated result. The mocked queryable. Sets up FromSqlInterpolated invocations to return a specified result. The queryable source type. The mocked queryable. The FromSqlInterpolated sql string. Set up supports case insensitive partial matches. The FromSqlInterpolated parameters. Set up supports case insensitive partial parameter sequence matching. The FromSqlInterpolated result. The mocked queryable. Sets up FromSqlRaw invocations to return a specified result. The queryable source type. The mocked queryable. The FromSqlRaw result. The mocked queryable. Sets up FromSqlRaw invocations containing a specified sql string to return a specified result. The queryable source type. The mocked queryable. The FromSqlRaw sql string. Set up supports case insensitive partial matches. The FromSqlRaw result. The mocked queryable. Sets up FromSqlRaw invocations containing a specified sql string and parameters to return a specified result. The queryable source type. The mocked queryable. The FromSqlRaw sql string. Set up supports case insensitive partial matches. The FromSqlRaw parameters. Set up supports case insensitive partial parameter sequence matching. The FromSqlRaw result. The mocked queryable. Extensions for collection query providers. Sets up FromSqlInterpolated invocations to return a specified result. The queryable source type. The mocked query provider. The FromSqlInterpolated result. The mocked queryable. Sets up FromSqlInterpolated invocations containing a specified sql string to return a specified result. The queryable source type. The mocked query provider. The FromSqlInterpolated sql string. Set up supports case insensitive partial matches. The FromSqlInterpolated result. The mocked queryable. Sets up FromSqlInterpolated invocations containing a specified sql string and parameters to return a specified result. The queryable source type. The mocked query provider. The FromSqlInterpolated sql string. Set up supports case insensitive partial matches. The FromSqlInterpolated parameters. Set up supports case insensitive partial parameter sequence matching. The sequence to return when FromSqlInterpolated is invoked. The mocked query provider. Sets up FromSqlRaw invocations to return a specified result. The queryable source type. The mocked query provider. The FromSqlRaw result. The mocked queryable. Sets up FromSqlRaw invocations containing a specified sql string to return a specified result. The queryable source type. The mocked query provider. The FromSqlRaw sql string. Set up supports case insensitive partial matches. The FromSqlRaw result. The mocked queryable. Sets up FromSqlRaw invocations containing a specified sql string and parameters to return a specified result. The queryable source type. The mocked query provider. The FromSqlRaw sql string. Set up supports case insensitive partial matches. The FromSqlRaw parameters. Set up supports case insensitive partial parameter sequence matching. The sequence to return when FromSqlRaw is invoked. The mocked query provider. Extensions for read-only db sets. Adds an item to the end of the mocked readonly db set source. The entity type. The mocked readonly db set. The item to be added to the end of the mocked readonly db set source. Adds the items of the specified sequence to the end of the mocked readonly db set source. The entity type. The mocked readonly db set. The sequence whose items should be added to the end of the mocked readonly db set source. Removes all items from the mocked readonly db set source. The entity type. The mocked readonly db set. The mocked db context builder. The db context type. Creates the mocked db context. A mocked db context. ================================================ FILE: src/EntityFrameworkCore.Testing.Moq/Extensions/DbContextExtensions.cs ================================================ #pragma warning disable EF1001 // Internal EF Core API usage. using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using EntityFrameworkCore.Testing.Common.Helpers; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.Extensions.Logging; using Moq; using rgvlee.Core.Common.Helpers; namespace EntityFrameworkCore.Testing.Moq.Extensions { /// /// Extensions for db contexts. /// public static class DbContextExtensions { private static readonly ILogger Logger = LoggingHelper.CreateLogger(typeof(DbContextExtensions)); /// /// Sets up ExecuteSqlInterpolated invocations to return a specified result. /// /// The db context type. /// The mocked db context. /// The integer to return when ExecuteSqlInterpolated is invoked. /// Operations to perform after ExecuteSqlCommand is invoked. /// The mocked db context. public static TDbContext AddExecuteSqlInterpolatedResult( this TDbContext mockedDbContext, int executeSqlInterpolatedResult, Action> callback = null) where TDbContext : DbContext { EnsureArgument.IsNotNull(mockedDbContext, nameof(mockedDbContext)); return mockedDbContext.AddExecuteSqlRawResult(string.Empty, new List(), executeSqlInterpolatedResult, callback); } /// /// Sets up ExecuteSqlInterpolated invocations containing a specified sql string to return a specified result. /// /// The db context type. /// The mocked db context. /// The ExecuteSqlInterpolated sql string. Set up supports case insensitive partial matches. /// The integer to return when ExecuteSqlInterpolated is invoked. /// Operations to perform after ExecuteSqlCommand is invoked. /// The mocked db context. public static TDbContext AddExecuteSqlInterpolatedResult( this TDbContext mockedDbContext, FormattableString sql, int executeSqlInterpolatedResult, Action> callback = null) where TDbContext : DbContext { EnsureArgument.IsNotNull(mockedDbContext, nameof(mockedDbContext)); return mockedDbContext.AddExecuteSqlRawResult(sql.Format, sql.GetArguments(), executeSqlInterpolatedResult, callback); } /// /// Sets up ExecuteSqlInterpolated invocations containing a specified sql string to return a specified result. /// /// The db context type. /// The mocked db context. /// The ExecuteSqlInterpolated sql string. Set up supports case insensitive partial matches. /// The ExecuteSqlInterpolated parameters. Set up supports case insensitive partial parameter sequence matching. /// The integer to return when ExecuteSqlInterpolated is invoked. /// Operations to perform after ExecuteSqlCommand is invoked. /// The mocked db context. public static TDbContext AddExecuteSqlInterpolatedResult( this TDbContext mockedDbContext, string sql, IEnumerable parameters, int executeSqlInterpolatedResult, Action> callback = null) where TDbContext : DbContext { EnsureArgument.IsNotNull(mockedDbContext, nameof(mockedDbContext)); return mockedDbContext.AddExecuteSqlRawResult(sql, parameters, executeSqlInterpolatedResult, callback); } /// /// Sets up ExecuteSqlRaw invocations to return a specified result. /// /// The db context type. /// The mocked db context. /// The integer to return when ExecuteSqlRaw is invoked. /// Operations to perform after ExecuteSqlCommand is invoked. /// The mocked db context. public static TDbContext AddExecuteSqlRawResult(this TDbContext mockedDbContext, int executeSqlRawResult, Action> callback = null) where TDbContext : DbContext { EnsureArgument.IsNotNull(mockedDbContext, nameof(mockedDbContext)); return mockedDbContext.AddExecuteSqlRawResult(string.Empty, new List(), executeSqlRawResult, callback); } /// /// Sets up ExecuteSqlRaw invocations containing a specified sql string and parameters to return a specified result. /// /// The db context type. /// The mocked db context. /// The ExecuteSqlRaw sql string. Set up supports case insensitive partial matches. /// The integer to return when ExecuteSqlRaw is invoked. /// Operations to perform after ExecuteSqlCommand is invoked. /// The mocked db context. public static TDbContext AddExecuteSqlRawResult( this TDbContext mockedDbContext, string sql, int executeSqlRawResult, Action> callback = null) where TDbContext : DbContext { EnsureArgument.IsNotNull(mockedDbContext, nameof(mockedDbContext)); return mockedDbContext.AddExecuteSqlRawResult(sql, new List(), executeSqlRawResult, callback); } /// /// Sets up ExecuteSqlRaw invocations containing a specified sql string and parameters to return a specified result. /// /// The db context type. /// The mocked db context. /// The ExecuteSqlRaw sql string. Set up supports case insensitive partial matches. /// The ExecuteSqlRaw parameters. Set up supports case insensitive partial parameter sequence matching. /// The integer to return when ExecuteSqlRaw is invoked. /// Operations to perform after ExecuteSqlCommand is invoked. /// The mocked db context. public static TDbContext AddExecuteSqlRawResult( this TDbContext mockedDbContext, string sql, IEnumerable parameters, int executeSqlRawResult, Action> callback = null) where TDbContext : DbContext { EnsureArgument.IsNotNull(mockedDbContext, nameof(mockedDbContext)); EnsureArgument.IsNotNull(sql, nameof(sql)); EnsureArgument.IsNotNull(parameters, nameof(parameters)); var relationalCommandMock = new Mock(); relationalCommandMock.Setup(m => m.ExecuteNonQuery(It.IsAny())) .Returns((RelationalCommandParameterObject providedRelationalCommandParameterObject) => executeSqlRawResult); relationalCommandMock.Setup(m => m.ExecuteNonQueryAsync(It.IsAny(), It.IsAny())) .Returns((RelationalCommandParameterObject providedRelationalCommandParameterObject, CancellationToken providedCancellationToken) => Task.FromResult(executeSqlRawResult)); var relationalCommand = relationalCommandMock.Object; var rawSqlCommandMock = new Mock(relationalCommand, new Dictionary()); rawSqlCommandMock.Setup(m => m.RelationalCommand).Returns(() => relationalCommand); rawSqlCommandMock.Setup(m => m.ParameterValues).Returns(() => new Dictionary()); var rawSqlCommand = rawSqlCommandMock.Object; var existingRawSqlCommandBuilder = ((IRelationalDatabaseFacadeDependencies) ((IInfrastructure) mockedDbContext).Instance.GetService(typeof(IDatabaseFacadeDependencies))) .RawSqlCommandBuilder; Mock.Get(existingRawSqlCommandBuilder) .Setup(m => m.Build( It.Is(s => s.Contains(sql, StringComparison.OrdinalIgnoreCase)), It.Is>(p => ParameterMatchingHelper.DoInvocationParametersMatchSetUpParameters(parameters, p)), It.IsAny())) .Returns((string _, IEnumerable _, IModel _) => rawSqlCommand) .Callback((string providedSql, IEnumerable providedParameters, IModel _) => { callback?.Invoke(providedSql, providedParameters); var parts = new List(); parts.Add($"Invocation sql: {providedSql}"); parts.Add("Invocation Parameters:"); parts.Add(ParameterMatchingHelper.StringifyParameters(providedParameters)); Logger.LogDebug(string.Join(Environment.NewLine, parts)); }); return mockedDbContext; } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Moq/Extensions/DbSetExtensions.Internal.cs ================================================ using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Threading; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Moq; using rgvlee.Core.Common.Helpers; namespace EntityFrameworkCore.Testing.Moq.Extensions { /// /// Extensions for db sets. /// public static class DbSetExtensions { internal static DbSet CreateMockedDbSet(this DbSet dbSet) where TEntity : class { EnsureArgument.IsNotNull(dbSet, nameof(dbSet)); var dbSetMock = new Mock>(); var mockedQueryProvider = ((IQueryable) dbSet).Provider.CreateMockedQueryProvider(dbSet); dbSetMock.Setup(m => m.Add(It.IsAny())).Returns((TEntity providedEntity) => dbSet.Add(providedEntity)); dbSetMock.Setup(m => m.AddAsync(It.IsAny(), It.IsAny())) .Returns((TEntity providedEntity, CancellationToken providedCancellationToken) => dbSet.AddAsync(providedEntity, providedCancellationToken)); dbSetMock.Setup(m => m.AddRange(It.IsAny>())).Callback((IEnumerable providedEntities) => dbSet.AddRange(providedEntities)); dbSetMock.Setup(m => m.AddRange(It.IsAny())).Callback((TEntity[] providedEntities) => dbSet.AddRange(providedEntities)); dbSetMock.Setup(m => m.AddRangeAsync(It.IsAny>(), It.IsAny())) .Returns((IEnumerable providedEntities, CancellationToken providedCancellationToken) => dbSet.AddRangeAsync(providedEntities, providedCancellationToken)); dbSetMock.Setup(m => m.AddRangeAsync(It.IsAny())).Returns((TEntity[] providedEntities) => dbSet.AddRangeAsync(providedEntities)); dbSetMock.Setup(m => m.Attach(It.IsAny())).Returns((TEntity providedEntity) => dbSet.Attach(providedEntity)); dbSetMock.Setup(m => m.AttachRange(It.IsAny>())).Callback((IEnumerable providedEntities) => dbSet.AttachRange(providedEntities)); dbSetMock.Setup(m => m.AttachRange(It.IsAny())).Callback((TEntity[] providedEntities) => dbSet.AttachRange(providedEntities)); dbSetMock.As().Setup(m => m.ContainsListCollection).Returns(() => ((IListSource) dbSet).ContainsListCollection); dbSetMock.As>().Setup(m => m.ElementType).Returns(() => ((IQueryable) dbSet).ElementType); dbSetMock.Setup(m => m.EntityType).Returns(() => dbSet.EntityType); dbSetMock.As>().Setup(m => m.Expression).Returns(() => ((IQueryable) dbSet).Expression); dbSetMock.Setup(m => m.Find(It.IsAny())).Returns((object[] providedKeyValues) => dbSet.Find(providedKeyValues)); dbSetMock.Setup(m => m.FindAsync(It.IsAny())).Returns((object[] providedKeyValues) => dbSet.FindAsync(providedKeyValues)); dbSetMock.Setup(m => m.FindAsync(It.IsAny(), It.IsAny())) .Returns((object[] providedKeyValues, CancellationToken providedCancellationToken) => dbSet.FindAsync(providedKeyValues, providedCancellationToken)); dbSetMock.As>() .Setup(m => m.GetAsyncEnumerator(It.IsAny())) .Returns((CancellationToken providedCancellationToken) => ((IAsyncEnumerable) dbSet).GetAsyncEnumerator(providedCancellationToken)); dbSetMock.As().Setup(m => m.GetEnumerator()).Returns(() => ((IEnumerable) dbSet).GetEnumerator()); dbSetMock.As>().Setup(m => m.GetEnumerator()).Returns(() => ((IEnumerable) dbSet).GetEnumerator()); /* * System.NotSupportedException : Data binding directly to a store query is not supported. Instead populate a DbSet with data, * 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 * databound control iterates the data. For WPF bind to 'DbSet.Local.ToObservableCollection()'. For WinForms bind to * 'DbSet.Local.ToBindingList()'. For ASP.NET WebForms bind to 'DbSet.ToList()' or use Model Binding. */ dbSetMock.As().Setup(m => m.GetList()).Returns(() => dbSet.ToList()); dbSetMock.As>().Setup(m => m.Instance).Returns(() => ((IInfrastructure) dbSet).Instance); dbSetMock.Setup(m => m.Local).Returns(() => dbSet.Local); dbSetMock.Setup(m => m.Remove(It.IsAny())).Returns((TEntity providedEntity) => dbSet.Remove(providedEntity)); dbSetMock.Setup(m => m.RemoveRange(It.IsAny>())).Callback((IEnumerable providedEntities) => dbSet.RemoveRange(providedEntities)); dbSetMock.Setup(m => m.RemoveRange(It.IsAny())).Callback((TEntity[] providedEntities) => dbSet.RemoveRange(providedEntities)); dbSetMock.Setup(m => m.Update(It.IsAny())).Returns((TEntity providedEntity) => dbSet.Update(providedEntity)); dbSetMock.Setup(m => m.UpdateRange(It.IsAny>())).Callback((IEnumerable providedEntities) => dbSet.UpdateRange(providedEntities)); dbSetMock.Setup(m => m.UpdateRange(It.IsAny())).Callback((TEntity[] providedEntities) => dbSet.UpdateRange(providedEntities)); dbSetMock.As>().Setup(m => m.Provider).Returns(() => mockedQueryProvider); dbSetMock.Setup(m => m.AsAsyncEnumerable()).Returns(() => dbSet.AsAsyncEnumerable()); dbSetMock.Setup(m => m.AsQueryable()).Returns(() => dbSet); return dbSetMock.Object; } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Moq/Extensions/QueryProviderExtensions.Internal.cs ================================================ using System.Collections.Generic; using System.Linq; using EntityFrameworkCore.Testing.Common; using Moq; using rgvlee.Core.Common.Helpers; namespace EntityFrameworkCore.Testing.Moq.Extensions { public static partial class QueryProviderExtensions { internal static IQueryProvider CreateMockedQueryProvider(this IQueryProvider queryProviderToMock, IEnumerable collection) where T : class { EnsureArgument.IsNotNull(queryProviderToMock, nameof(queryProviderToMock)); EnsureArgument.IsNotNull(collection, nameof(collection)); var queryProviderMock = new Mock>(collection); queryProviderMock.CallBase = true; return queryProviderMock.Object; } internal static void SetSource(this AsyncQueryProvider mockedQueryProvider, IEnumerable source) where T : class { EnsureArgument.IsNotNull(mockedQueryProvider, nameof(mockedQueryProvider)); EnsureArgument.IsNotNull(source, nameof(source)); mockedQueryProvider.Source = source.AsQueryable(); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Moq/Extensions/QueryProviderExtensions.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using EntityFrameworkCore.Testing.Common; using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.Extensions.Logging; using Moq; using rgvlee.Core.Common.Helpers; using ProjectExpressionHelper = EntityFrameworkCore.Testing.Common.Helpers.ExpressionHelper; namespace EntityFrameworkCore.Testing.Moq.Extensions { /// /// Extensions for collection query providers. /// public static partial class QueryProviderExtensions { private static readonly ILogger Logger = LoggingHelper.CreateLogger(typeof(QueryProviderExtensions)); /// /// Sets up FromSqlInterpolated invocations to return a specified result. /// /// The queryable source type. /// The mocked query provider. /// The FromSqlInterpolated result. /// The mocked queryable. public static IQueryProvider AddFromSqlInterpolatedResult(this IQueryProvider mockedQueryProvider, IEnumerable fromSqlInterpolatedResult) where T : class { EnsureArgument.IsNotNull(mockedQueryProvider, nameof(mockedQueryProvider)); mockedQueryProvider.AddFromSqlRawResult(string.Empty, new List(), fromSqlInterpolatedResult); return mockedQueryProvider; } /// /// Sets up FromSqlInterpolated invocations containing a specified sql string to return a specified result. /// /// The queryable source type. /// The mocked query provider. /// The FromSqlInterpolated sql string. Set up supports case insensitive partial matches. /// The FromSqlInterpolated result. /// The mocked queryable. public static IQueryProvider AddFromSqlInterpolatedResult(this IQueryProvider mockedQueryProvider, FormattableString sql, IEnumerable fromSqlInterpolatedResult) where T : class { EnsureArgument.IsNotNull(mockedQueryProvider, nameof(mockedQueryProvider)); mockedQueryProvider.AddFromSqlRawResult(sql.Format, sql.GetArguments(), fromSqlInterpolatedResult); return mockedQueryProvider; } /// /// Sets up FromSqlInterpolated invocations containing a specified sql string and parameters to return a specified result. /// /// The queryable source type. /// The mocked query provider. /// The FromSqlInterpolated sql string. Set up supports case insensitive partial matches. /// The FromSqlInterpolated parameters. Set up supports case insensitive partial parameter sequence matching. /// The sequence to return when FromSqlInterpolated is invoked. /// The mocked query provider. public static IQueryProvider AddFromSqlInterpolatedResult( this IQueryProvider mockedQueryProvider, string sql, IEnumerable parameters, IEnumerable fromSqlInterpolatedResult) where T : class { EnsureArgument.IsNotNull(mockedQueryProvider, nameof(mockedQueryProvider)); mockedQueryProvider.AddFromSqlRawResult(sql, parameters, fromSqlInterpolatedResult); return mockedQueryProvider; } /// /// Sets up FromSqlRaw invocations to return a specified result. /// /// The queryable source type. /// The mocked query provider. /// The FromSqlRaw result. /// The mocked queryable. public static IQueryProvider AddFromSqlRawResult(this IQueryProvider mockedQueryProvider, IEnumerable fromSqlRawResult) where T : class { EnsureArgument.IsNotNull(mockedQueryProvider, nameof(mockedQueryProvider)); mockedQueryProvider.AddFromSqlRawResult(string.Empty, new List(), fromSqlRawResult); return mockedQueryProvider; } /// /// Sets up FromSqlRaw invocations containing a specified sql string to return a specified result. /// /// The queryable source type. /// The mocked query provider. /// The FromSqlRaw sql string. Set up supports case insensitive partial matches. /// The FromSqlRaw result. /// The mocked queryable. public static IQueryProvider AddFromSqlRawResult(this IQueryProvider mockedQueryProvider, string sql, IEnumerable fromSqlRawResult) where T : class { EnsureArgument.IsNotNull(mockedQueryProvider, nameof(mockedQueryProvider)); mockedQueryProvider.AddFromSqlRawResult(sql, new List(), fromSqlRawResult); return mockedQueryProvider; } /// /// Sets up FromSqlRaw invocations containing a specified sql string and parameters to return a specified result. /// /// The queryable source type. /// The mocked query provider. /// The FromSqlRaw sql string. Set up supports case insensitive partial matches. /// The FromSqlRaw parameters. Set up supports case insensitive partial parameter sequence matching. /// The sequence to return when FromSqlRaw is invoked. /// The mocked query provider. public static IQueryProvider AddFromSqlRawResult(this IQueryProvider mockedQueryProvider, string sql, IEnumerable parameters, IEnumerable fromSqlResult) where T : class { EnsureArgument.IsNotNull(mockedQueryProvider, nameof(mockedQueryProvider)); EnsureArgument.IsNotNull(sql, nameof(sql)); EnsureArgument.IsNotNull(parameters, nameof(parameters)); EnsureArgument.IsNotNull(fromSqlResult, nameof(fromSqlResult)); Logger.LogDebug("Setting up '{sql}'", sql); var createQueryResult = new AsyncEnumerable(fromSqlResult); Mock.Get(mockedQueryProvider) .Setup(m => m.CreateQuery(It.Is(fsqre => ProjectExpressionHelper.SqlAndParametersMatchFromSqlExpression(sql, parameters, fsqre)))) .Returns((Expression providedExpression) => { ProjectExpressionHelper.ThrowIfExpressionIsNotSupported(providedExpression); return createQueryResult; }) .Callback((Expression providedExpression) => { var fsqre = (FromSqlQueryRootExpression) providedExpression; var parts = new List(); parts.Add("FromSql inputs:"); parts.Add(ProjectExpressionHelper.StringifyFromSqlExpression(fsqre)); Logger.LogDebug(string.Join(Environment.NewLine, parts)); }); return mockedQueryProvider; } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Moq/Extensions/QueryableExtensions.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using rgvlee.Core.Common.Helpers; namespace EntityFrameworkCore.Testing.Moq.Extensions { /// /// Extensions for queryable collections. /// public static class QueryableExtensions { /// /// Sets up FromSqlInterpolated invocations to return a specified result. /// /// The queryable source type. /// The mocked queryable. /// The FromSqlInterpolated result. /// The mocked queryable. public static IQueryable AddFromSqlInterpolatedResult(this IQueryable mockedQueryable, IEnumerable fromSqlInterpolatedResult) where T : class { EnsureArgument.IsNotNull(mockedQueryable, nameof(mockedQueryable)); mockedQueryable.Provider.AddFromSqlRawResult(string.Empty, new List(), fromSqlInterpolatedResult); return mockedQueryable; } /// /// Sets up FromSqlInterpolated invocations to return a specified result. /// /// The queryable source type. /// The mocked queryable. /// The FromSqlInterpolated sql string. Set up supports case insensitive partial matches. /// The FromSqlInterpolated result. /// The mocked queryable. public static IQueryable AddFromSqlInterpolatedResult(this IQueryable mockedQueryable, FormattableString sql, IEnumerable fromSqlInterpolatedResult) where T : class { EnsureArgument.IsNotNull(mockedQueryable, nameof(mockedQueryable)); mockedQueryable.Provider.AddFromSqlRawResult(sql.Format, sql.GetArguments(), fromSqlInterpolatedResult); return mockedQueryable; } /// /// Sets up FromSqlInterpolated invocations to return a specified result. /// /// The queryable source type. /// The mocked queryable. /// The FromSqlInterpolated sql string. Set up supports case insensitive partial matches. /// The FromSqlInterpolated parameters. Set up supports case insensitive partial parameter sequence matching. /// The FromSqlInterpolated result. /// The mocked queryable. public static IQueryable AddFromSqlInterpolatedResult( this IQueryable mockedQueryable, string sql, IEnumerable parameters, IEnumerable fromSqlInterpolatedResult) where T : class { EnsureArgument.IsNotNull(mockedQueryable, nameof(mockedQueryable)); mockedQueryable.Provider.AddFromSqlRawResult(sql, parameters, fromSqlInterpolatedResult); return mockedQueryable; } /// /// Sets up FromSqlRaw invocations to return a specified result. /// /// The queryable source type. /// The mocked queryable. /// The FromSqlRaw result. /// The mocked queryable. public static IQueryable AddFromSqlRawResult(this IQueryable mockedQueryable, IEnumerable fromSqlRawResult) where T : class { EnsureArgument.IsNotNull(mockedQueryable, nameof(mockedQueryable)); mockedQueryable.Provider.AddFromSqlRawResult(string.Empty, new List(), fromSqlRawResult); return mockedQueryable; } /// /// Sets up FromSqlRaw invocations containing a specified sql string to return a specified result. /// /// The queryable source type. /// The mocked queryable. /// The FromSqlRaw sql string. Set up supports case insensitive partial matches. /// The FromSqlRaw result. /// The mocked queryable. public static IQueryable AddFromSqlRawResult(this IQueryable mockedQueryable, string sql, IEnumerable fromSqlRawResult) where T : class { EnsureArgument.IsNotNull(mockedQueryable, nameof(mockedQueryable)); mockedQueryable.Provider.AddFromSqlRawResult(sql, new List(), fromSqlRawResult); return mockedQueryable; } /// /// Sets up FromSqlRaw invocations containing a specified sql string and parameters to return a specified result. /// /// The queryable source type. /// The mocked queryable. /// The FromSqlRaw sql string. Set up supports case insensitive partial matches. /// The FromSqlRaw parameters. Set up supports case insensitive partial parameter sequence matching. /// The FromSqlRaw result. /// The mocked queryable. public static IQueryable AddFromSqlRawResult(this IQueryable mockedQueryable, string sql, IEnumerable parameters, IEnumerable fromSqlRawResult) where T : class { EnsureArgument.IsNotNull(mockedQueryable, nameof(mockedQueryable)); mockedQueryable.Provider.AddFromSqlRawResult(sql, parameters, fromSqlRawResult); return mockedQueryable; } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Moq/Extensions/ReadOnlyDbSetExtensions.Internal.cs ================================================ using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Threading; using EntityFrameworkCore.Testing.Common; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Query; using Moq; using rgvlee.Core.Common.Helpers; namespace EntityFrameworkCore.Testing.Moq.Extensions { public static partial class ReadOnlyDbSetExtensions { internal static DbSet CreateMockedReadOnlyDbSet(this DbSet readOnlyDbSet) where TEntity : class { EnsureArgument.IsNotNull(readOnlyDbSet, nameof(readOnlyDbSet)); var readOnlyDbSetMock = new Mock>(); var asyncEnumerable = new AsyncEnumerable(new List(), new FakeQueryRootExpression(Mock.Of(), readOnlyDbSet.EntityType)); var mockedQueryProvider = ((IQueryable) readOnlyDbSet).Provider.CreateMockedQueryProvider(asyncEnumerable); var invalidOperationException = new InvalidOperationException( $"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."); readOnlyDbSetMock.Setup(m => m.Add(It.IsAny())).Throws(invalidOperationException); readOnlyDbSetMock.Setup(m => m.AddAsync(It.IsAny(), It.IsAny())).Throws(invalidOperationException); readOnlyDbSetMock.Setup(m => m.AddRange(It.IsAny>())).Throws(invalidOperationException); readOnlyDbSetMock.Setup(m => m.AddRange(It.IsAny())).Throws(invalidOperationException); readOnlyDbSetMock.Setup(m => m.AddRangeAsync(It.IsAny>(), It.IsAny())).Throws(invalidOperationException); readOnlyDbSetMock.Setup(m => m.AddRangeAsync(It.IsAny())).Throws(invalidOperationException); readOnlyDbSetMock.Setup(m => m.Attach(It.IsAny())).Throws(invalidOperationException); readOnlyDbSetMock.Setup(m => m.AttachRange(It.IsAny>())).Throws(invalidOperationException); readOnlyDbSetMock.Setup(m => m.AttachRange(It.IsAny())).Throws(invalidOperationException); readOnlyDbSetMock.As().Setup(m => m.ContainsListCollection).Returns(() => false); readOnlyDbSetMock.As>().Setup(m => m.ElementType).Returns(() => asyncEnumerable.ElementType); readOnlyDbSetMock.Setup(m => m.EntityType).Returns(() => readOnlyDbSet.EntityType); readOnlyDbSetMock.As>().Setup(m => m.Expression).Returns(() => asyncEnumerable.Expression); readOnlyDbSetMock.Setup(m => m.Find(It.IsAny())).Throws(new InvalidOperationException($"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.")); readOnlyDbSetMock.Setup(m => m.FindAsync(It.IsAny())).Throws(new InvalidOperationException($"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.")); readOnlyDbSetMock.Setup(m => m.FindAsync(It.IsAny(), It.IsAny())).Throws(new InvalidOperationException($"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.")); readOnlyDbSetMock.As>() .Setup(m => m.GetAsyncEnumerator(It.IsAny())) .Returns((CancellationToken providedCancellationToken) => asyncEnumerable.GetAsyncEnumerator(providedCancellationToken)); readOnlyDbSetMock.As().Setup(m => m.GetEnumerator()).Returns(() => ((IEnumerable) asyncEnumerable).GetEnumerator()); readOnlyDbSetMock.As>().Setup(m => m.GetEnumerator()).Returns(() => ((IEnumerable) asyncEnumerable).GetEnumerator()); readOnlyDbSetMock.As().Setup(m => m.GetList()).Returns(() => asyncEnumerable.ToList()); readOnlyDbSetMock.As>().Setup(m => m.Instance).Returns(() => ((IInfrastructure) readOnlyDbSet).Instance); readOnlyDbSetMock.Setup(m => m.Local) .Throws(new InvalidOperationException($"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.")); readOnlyDbSetMock.Setup(m => m.Remove(It.IsAny())).Throws(invalidOperationException); readOnlyDbSetMock.Setup(m => m.RemoveRange(It.IsAny>())).Throws(invalidOperationException); readOnlyDbSetMock.Setup(m => m.RemoveRange(It.IsAny())).Throws(invalidOperationException); readOnlyDbSetMock.Setup(m => m.Update(It.IsAny())).Throws(invalidOperationException); readOnlyDbSetMock.Setup(m => m.UpdateRange(It.IsAny>())).Throws(invalidOperationException); readOnlyDbSetMock.Setup(m => m.UpdateRange(It.IsAny())).Throws(invalidOperationException); readOnlyDbSetMock.As>().Setup(m => m.Provider).Returns(() => mockedQueryProvider); readOnlyDbSetMock.Setup(m => m.AsAsyncEnumerable()).Returns(() => asyncEnumerable); readOnlyDbSetMock.Setup(m => m.AsQueryable()).Returns(() => asyncEnumerable); return readOnlyDbSetMock.Object; } internal static void SetSource(this DbSet mockedReadOnlyDbSet, IEnumerable source) where TEntity : class { EnsureArgument.IsNotNull(mockedReadOnlyDbSet, nameof(mockedReadOnlyDbSet)); EnsureArgument.IsNotNull(source, nameof(source)); var readOnlyDbSetMock = Mock.Get(mockedReadOnlyDbSet); var asyncEnumerable = new AsyncEnumerable(source, new FakeQueryRootExpression(Mock.Of(), mockedReadOnlyDbSet.EntityType)); var mockedQueryProvider = ((IQueryable) mockedReadOnlyDbSet).Provider; readOnlyDbSetMock.As>().Setup(m => m.Expression).Returns(() => asyncEnumerable.Expression); readOnlyDbSetMock.As>() .Setup(m => m.GetAsyncEnumerator(It.IsAny())) .Returns((CancellationToken providedCancellationToken) => asyncEnumerable.GetAsyncEnumerator(providedCancellationToken)); readOnlyDbSetMock.As().Setup(m => m.GetEnumerator()).Returns(() => ((IEnumerable) asyncEnumerable).GetEnumerator()); readOnlyDbSetMock.As>().Setup(m => m.GetEnumerator()).Returns(() => ((IEnumerable) asyncEnumerable).GetEnumerator()); readOnlyDbSetMock.As().Setup(m => m.GetList()).Returns(() => asyncEnumerable.ToList()); readOnlyDbSetMock.Setup(m => m.AsAsyncEnumerable()).Returns(() => asyncEnumerable); readOnlyDbSetMock.Setup(m => m.AsQueryable()).Returns(() => asyncEnumerable); ((AsyncQueryProvider) mockedQueryProvider).SetSource(asyncEnumerable); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Moq/Extensions/ReadOnlyDbSetExtensions.cs ================================================ using System.Collections.Generic; using System.Linq; using Microsoft.EntityFrameworkCore; using rgvlee.Core.Common.Helpers; namespace EntityFrameworkCore.Testing.Moq.Extensions { /// /// Extensions for read-only db sets. /// public static partial class ReadOnlyDbSetExtensions { /// /// Adds an item to the end of the mocked readonly db set source. /// /// The entity type. /// The mocked readonly db set. /// The item to be added to the end of the mocked readonly db set source. public static void AddToReadOnlySource(this DbSet mockedReadOnlyDbSet, TEntity item) where TEntity : class { EnsureArgument.IsNotNull(mockedReadOnlyDbSet, nameof(mockedReadOnlyDbSet)); EnsureArgument.IsNotNull(item, nameof(item)); var list = mockedReadOnlyDbSet.ToList(); list.Add(item); mockedReadOnlyDbSet.SetSource(list); } /// /// Adds the items of the specified sequence to the end of the mocked readonly db set source. /// /// The entity type. /// The mocked readonly db set. /// The sequence whose items should be added to the end of the mocked readonly db set source. public static void AddRangeToReadOnlySource(this DbSet mockedReadOnlyDbSet, IEnumerable items) where TEntity : class { EnsureArgument.IsNotNull(mockedReadOnlyDbSet, nameof(mockedReadOnlyDbSet)); EnsureArgument.IsNotEmpty(items, nameof(items)); var list = mockedReadOnlyDbSet.ToList(); list.AddRange(items); mockedReadOnlyDbSet.SetSource(list); } /// /// Removes all items from the mocked readonly db set source. /// /// The entity type. /// The mocked readonly db set. public static void ClearReadOnlySource(this DbSet mockedReadOnlyDbSet) where TEntity : class { EnsureArgument.IsNotNull(mockedReadOnlyDbSet, nameof(mockedReadOnlyDbSet)); mockedReadOnlyDbSet.SetSource(new List()); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Moq/Helpers/MockedDbContextBuilder.cs ================================================ using EntityFrameworkCore.Testing.Common.Helpers; using Microsoft.EntityFrameworkCore; namespace EntityFrameworkCore.Testing.Moq.Helpers { /// /// The mocked db context builder. /// /// The db context type. public class MockedDbContextBuilder : BaseMockedDbContextBuilder where TDbContext : DbContext { /// /// Creates the mocked db context. /// /// A mocked db context. public override TDbContext MockedDbContext => new MockedDbContextFactory(Options).Create(); } } ================================================ FILE: src/EntityFrameworkCore.Testing.Moq/Helpers/MockedDbContextFactory.Internal.cs ================================================ #pragma warning disable EF1001 // Internal EF Core API usage. using System; using System.Collections.Generic; using System.Threading; using EntityFrameworkCore.Testing.Common.Helpers; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.Extensions.Logging; using Moq; namespace EntityFrameworkCore.Testing.Moq.Helpers { internal class MockedDbContextFactory : BaseMockedDbContextFactory where TDbContext : DbContext { public MockedDbContextFactory(MockedDbContextFactoryOptions options) : base(options) { } public override TDbContext Create() { var dbContextMock = new Mock(ConstructorParameters.ToArray()); dbContextMock.DefaultValueProvider = new NoSetUpDefaultValueProvider(DbContext); dbContextMock.Setup(m => m.Add(It.IsAny())).Returns((object providedEntity) => DbContext.Add(providedEntity)); dbContextMock.Setup(m => m.AddAsync(It.IsAny(), It.IsAny())) .Returns((object providedEntity, CancellationToken providedCancellationToken) => DbContext.AddAsync(providedEntity, providedCancellationToken)); dbContextMock.Setup(m => m.AddRange(It.IsAny())).Callback((object[] providedEntities) => DbContext.AddRange(providedEntities)); dbContextMock.Setup(m => m.AddRange(It.IsAny>())).Callback((IEnumerable providedEntities) => DbContext.AddRange(providedEntities)); dbContextMock.Setup(m => m.AddRangeAsync(It.IsAny(), It.IsAny())) .Returns((object[] providedEntities, CancellationToken providedCancellationToken) => DbContext.AddRangeAsync(providedEntities, providedCancellationToken)); dbContextMock.Setup(m => m.AddRangeAsync(It.IsAny>(), It.IsAny())) .Returns((IEnumerable providedEntities, CancellationToken providedCancellationToken) => DbContext.AddRangeAsync(providedEntities, providedCancellationToken)); dbContextMock.Setup(m => m.Attach(It.IsAny())).Returns((object providedEntity) => DbContext.Attach(providedEntity)); dbContextMock.Setup(m => m.AttachRange(It.IsAny())).Callback((object[] providedEntities) => DbContext.AttachRange(providedEntities)); dbContextMock.Setup(m => m.AttachRange(It.IsAny>())).Callback((IEnumerable providedEntities) => DbContext.AttachRange(providedEntities)); dbContextMock.As().Setup(m => m.ChangeDetector).Returns(((IDbContextDependencies) DbContext).ChangeDetector); dbContextMock.Setup(m => m.ChangeTracker).Returns(() => DbContext.ChangeTracker); dbContextMock.Setup(m => m.ContextId).Returns(() => DbContext.ContextId); dbContextMock.Setup(m => m.Database).Returns(() => DbContext.Database); dbContextMock.Setup(m => m.Dispose()).Callback(() => DbContext.Dispose()); dbContextMock.Setup(m => m.DisposeAsync()).Callback(() => DbContext.DisposeAsync()); dbContextMock.As().Setup(m => m.EntityFinderFactory).Returns(((IDbContextDependencies) DbContext).EntityFinderFactory); dbContextMock.As().Setup(m => m.EntityGraphAttacher).Returns(((IDbContextDependencies) DbContext).EntityGraphAttacher); dbContextMock.Setup(m => m.Entry(It.IsAny())).Returns((object providedEntity) => DbContext.Entry(providedEntity)); dbContextMock.Setup(m => m.Find(It.IsAny(), It.IsAny())) .Returns((Type providedEntityType, object[] providedKeyValues) => DbContext.Find(providedEntityType, providedKeyValues)); dbContextMock.Setup(m => m.FindAsync(It.IsAny(), It.IsAny())) .Returns((Type providedEntityType, object[] providedKeyValues) => DbContext.FindAsync(providedEntityType, providedKeyValues)); dbContextMock.Setup(m => m.FindAsync(It.IsAny(), It.IsAny(), It.IsAny())) .Returns((Type providedEntityType, object[] providedKeyValues, CancellationToken providedCancellationToken) => DbContext.FindAsync(providedEntityType, providedKeyValues, providedCancellationToken)); dbContextMock.As() .Setup(m => m.GetOrAddSet(It.IsAny(), It.IsAny())) .Returns((IDbSetSource providedSource, Type providedType) => ((IDbSetCache) DbContext).GetOrAddSet(providedSource, providedType)); dbContextMock.As().Setup(m => m.InfrastructureLogger).Returns(((IDbContextDependencies) DbContext).InfrastructureLogger); dbContextMock.As>().Setup(m => m.Instance).Returns(((IInfrastructure) DbContext).Instance); //dbContextMock.As().Setup(m => m.Model).Returns(((IDbContextDependencies) DbContext).Model); dbContextMock.As().Setup(m => m.QueryProvider).Returns(((IDbContextDependencies) DbContext).QueryProvider); dbContextMock.Setup(m => m.Remove(It.IsAny())).Returns((object providedEntity) => DbContext.Remove(providedEntity)); dbContextMock.Setup(m => m.RemoveRange(It.IsAny>())).Callback((IEnumerable providedEntities) => DbContext.RemoveRange(providedEntities)); dbContextMock.Setup(m => m.RemoveRange(It.IsAny())).Callback((object[] providedEntities) => DbContext.RemoveRange(providedEntities)); dbContextMock.As().Setup(m => m.ResetState()).Callback(((IDbContextPoolable) DbContext).ResetState); dbContextMock.As() .Setup(m => m.ResetStateAsync(It.IsAny())) .Callback((CancellationToken providedCancellationToken) => ((IDbContextPoolable) DbContext).ResetStateAsync(providedCancellationToken)); // dbContextMock.As() // .Setup(m => m.Resurrect(It.IsAny())) // .Callback((DbContextPoolConfigurationSnapshot providedConfigurationSnapshot) => ((IDbContextPoolable) DbContext).Resurrect(providedConfigurationSnapshot)); dbContextMock.Setup(m => m.SaveChanges()).Returns(() => DbContext.SaveChanges()); dbContextMock.Setup(m => m.SaveChanges(It.IsAny())).Returns((bool providedAcceptAllChangesOnSuccess) => DbContext.SaveChanges(providedAcceptAllChangesOnSuccess)); dbContextMock.Setup(m => m.SaveChangesAsync(It.IsAny())) .Returns((CancellationToken providedCancellationToken) => DbContext.SaveChangesAsync(providedCancellationToken)); dbContextMock.Setup(m => m.SaveChangesAsync(It.IsAny(), It.IsAny())) .Returns((bool providedAcceptAllChangesOnSuccess, CancellationToken providedCancellationToken) => DbContext.SaveChangesAsync(providedAcceptAllChangesOnSuccess, providedCancellationToken)); // dbContextMock.As() // .Setup(m => m.SetPool(It.IsAny())) // .Callback((IDbContextPool providedContextPool) => ((IDbContextPoolable) DbContext).SetPool(providedContextPool)); dbContextMock.As().Setup(m => m.SetSource).Returns(((IDbContextDependencies) DbContext).SetSource); // dbContextMock.As().Setup(m => m.SnapshotConfiguration()).Returns(((IDbContextPoolable) DbContext).SnapshotConfiguration()); dbContextMock.As().Setup(m => m.StateManager).Returns(((IDbContextDependencies) DbContext).StateManager); dbContextMock.Setup(m => m.Update(It.IsAny())).Returns((object providedEntity) => DbContext.Update(providedEntity)); dbContextMock.As().Setup(m => m.UpdateLogger).Returns(((IDbContextDependencies) DbContext).UpdateLogger); dbContextMock.Setup(m => m.UpdateRange(It.IsAny>())).Callback((IEnumerable providedEntities) => DbContext.UpdateRange(providedEntities)); dbContextMock.Setup(m => m.UpdateRange(It.IsAny())).Callback((object[] providedEntities) => DbContext.UpdateRange(providedEntities)); //Relational set up var rawSqlCommandBuilderMock = new Mock(); rawSqlCommandBuilderMock.Setup(m => m.Build(It.IsAny(), It.IsAny>(), It.IsAny())) .Callback((string _, IEnumerable _, IModel _) => Logger.LogDebug("Catch all exception invoked")) .Throws(); var rawSqlCommandBuilder = rawSqlCommandBuilderMock.Object; // var concurrencyDetectorMock = new Mock(); // concurrencyDetectorMock.Setup(x => x.EnterCriticalSection()).Returns(() => new ConcurrencyDetectorCriticalSectionDisposer(Mock.Of())); // var concurrencyDetector = concurrencyDetectorMock.Object; var relationalConnectionMock = new Mock(); relationalConnectionMock.Setup(x => x.CommandTimeout).Returns(() => 0); var relationalConnection = relationalConnectionMock.Object; var dependenciesMock = new Mock(); //dependenciesMock.Setup(m => m.ConcurrencyDetector).Returns(() => concurrencyDetector); dependenciesMock.Setup(m => m.CommandLogger).Returns(() => Mock.Of()); dependenciesMock.Setup(m => m.RawSqlCommandBuilder).Returns(() => rawSqlCommandBuilder); dependenciesMock.Setup(m => m.RelationalConnection).Returns(() => relationalConnection); //dependenciesMock.Setup(m => m.CoreOptions.IsConcurrencyDetectionEnabled).Returns(() => true); dependenciesMock.Setup(m => m.CoreOptions.AreThreadSafetyChecksEnabled).Returns(() => false); var dependencies = dependenciesMock.Object; var serviceProviderMock = new Mock(); serviceProviderMock.Setup(m => m.GetService(It.Is(t => t == typeof(IDatabaseFacadeDependencies)))).Returns((Type providedType) => dependencies); serviceProviderMock.Setup(m => m.GetService(It.Is(t => t == typeof(IModel)))).Returns((Type _) => new Mock().Object); var serviceProvider = serviceProviderMock.Object; dbContextMock.As>().Setup(m => m.Instance).Returns(() => serviceProvider); var mockedDbContext = dbContextMock.Object; var databaseFacadeMock = new Mock(mockedDbContext); databaseFacadeMock.As().Setup(x => x.Dependencies).Returns(() => dependencies); databaseFacadeMock.Setup(x => x.BeginTransaction()).Returns(() => Mock.Of()); databaseFacadeMock.Setup(x => x.BeginTransactionAsync(It.IsAny())).ReturnsAsync(() => Mock.Of()); var databaseFacade = databaseFacadeMock.Object; dbContextMock.Setup(m => m.Database).Returns(() => databaseFacade); return mockedDbContext; } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Moq/Helpers/NoSetUpDefaultValueProvider.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Threading; using EntityFrameworkCore.Testing.Common; using EntityFrameworkCore.Testing.Moq.Extensions; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.Extensions.Logging; using Moq; using rgvlee.Core.Common.Extensions; using rgvlee.Core.Common.Helpers; using ProjectExpressionHelper = EntityFrameworkCore.Testing.Common.Helpers.ExpressionHelper; namespace EntityFrameworkCore.Testing.Moq.Helpers { internal class NoSetUpDefaultValueProvider : DefaultValueProvider where TDbContext : DbContext { private static readonly ILogger> Logger = LoggingHelper.CreateLogger>(); private readonly List _allModelEntityTypes; private readonly TDbContext _dbContext; private readonly List _dbContextModelProperties; public NoSetUpDefaultValueProvider(TDbContext dbContext) { _dbContext = dbContext; _allModelEntityTypes = _dbContext.Model.GetEntityTypes().ToList(); _dbContextModelProperties = _dbContext.GetType() .GetProperties() .Where(x => x.PropertyType.IsGenericType && x.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>)) .ToList(); } protected override object GetDefaultValue(Type type, Mock mock) { var dbContextMock = mock; var lastInvocation = mock.Invocations.Last(); var invokedMethod = lastInvocation.Method; var arguments = lastInvocation.Arguments; var modelType = GetModelType(invokedMethod); if (modelType == null) { return invokedMethod.ReturnType.GetDefaultValue(); } Logger.LogDebug("Setting up model '{type}'", modelType); var modelEntityType = _allModelEntityTypes.SingleOrDefault(x => x.ClrType.Equals(modelType)); if (modelEntityType == null) { throw new InvalidOperationException(string.Format(ExceptionMessages.CannotCreateDbSetTypeNotIncludedInModel, invokedMethod.GetGenericArguments().Single().Name)); } var setUpModelMethod = typeof(NoSetUpDefaultValueProvider).GetMethods(BindingFlags.Instance | BindingFlags.NonPublic) .Single(x => x.Name.Equals(modelEntityType.FindPrimaryKey() != null ? "SetUpModel" : "SetUpReadOnlyModel")); setUpModelMethod.MakeGenericMethod(modelType).Invoke(this, new[] { dbContextMock }); return invokedMethod.Invoke(dbContextMock.Object, arguments?.ToArray()); } private Type GetModelType(MethodInfo invokedMethod) { var dbContextModelProperty = _dbContextModelProperties.SingleOrDefault(x => x.GetMethod.Name.Equals(invokedMethod.Name)); if (dbContextModelProperty != null) { return dbContextModelProperty.PropertyType.GetGenericArguments().Single(); } if (!invokedMethod.IsGenericMethod) { return null; } var dbContextMethod = typeof(DbContext).GetMethods(BindingFlags.Instance | BindingFlags.Public) .SingleOrDefault(x => x.IsGenericMethod && x.GetGenericMethodDefinition().Equals(invokedMethod.GetGenericMethodDefinition())); if (dbContextMethod != null) { return invokedMethod.GetGenericArguments().Single(); } return null; } private void SetUpModel(Mock dbContextMock) where TEntity : class { var mockedDbSet = _dbContext.Set().CreateMockedDbSet(); var property = typeof(TDbContext).GetProperties().SingleOrDefault(p => p.PropertyType == typeof(DbSet)); if (property != null) { var propertyExpression = ProjectExpressionHelper.CreatePropertyExpression>(property); dbContextMock.Setup(propertyExpression).Returns(() => mockedDbSet); } else { Logger.LogDebug("Could not find a DbContext property for type '{type}'", typeof(TEntity)); } dbContextMock.Setup(m => m.Set()).Returns(() => mockedDbSet); dbContextMock.Setup(m => m.Add(It.IsAny())).Returns((TEntity providedEntity) => _dbContext.Add(providedEntity)); dbContextMock.Setup(m => m.AddAsync(It.IsAny(), It.IsAny())) .Returns((TEntity providedEntity, CancellationToken providedCancellationToken) => _dbContext.AddAsync(providedEntity, providedCancellationToken)); dbContextMock.Setup(m => m.Attach(It.IsAny())).Returns((TEntity providedEntity) => _dbContext.Attach(providedEntity)); dbContextMock.Setup(m => m.Entry(It.IsAny())).Returns((TEntity providedEntity) => _dbContext.Entry(providedEntity)); dbContextMock.Setup(m => m.Find(It.IsAny())).Returns((object[] providedKeyValues) => _dbContext.Find(providedKeyValues)); dbContextMock.Setup(m => m.FindAsync(It.IsAny())).Returns((object[] providedKeyValues) => _dbContext.FindAsync(providedKeyValues)); dbContextMock.Setup(m => m.FindAsync(It.IsAny(), It.IsAny())) .Returns((object[] providedKeyValues, CancellationToken providedCancellationToken) => _dbContext.FindAsync(providedKeyValues, providedCancellationToken)); dbContextMock.Setup(m => m.Remove(It.IsAny())).Returns((TEntity providedEntity) => _dbContext.Remove(providedEntity)); dbContextMock.Setup(m => m.Update(It.IsAny())).Returns((TEntity providedEntity) => _dbContext.Update(providedEntity)); } private void SetUpReadOnlyModel(Mock dbContextMock) where TEntity : class { var mockedReadOnlyDbSet = _dbContext.Set().CreateMockedReadOnlyDbSet(); var property = typeof(TDbContext).GetProperties().SingleOrDefault(p => p.PropertyType == typeof(DbSet)); if (property != null) { var propertyExpression = ProjectExpressionHelper.CreatePropertyExpression>(property); dbContextMock.Setup(propertyExpression).Returns(() => mockedReadOnlyDbSet); } else { Logger.LogDebug("Could not find a DbContext property for type '{type}'", typeof(TEntity)); } dbContextMock.Setup(m => m.Set()).Returns(() => mockedReadOnlyDbSet); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Moq.Tests/BaseForDbContextTests.cs ================================================ using System; using System.Collections.Generic; using EntityFrameworkCore.Testing.Moq.Extensions; using Microsoft.EntityFrameworkCore; namespace EntityFrameworkCore.Testing.Moq.Tests { public abstract class BaseForDbContextTests : Common.Tests.BaseForDbContextTests where T : DbContext { public override void AddExecuteSqlInterpolatedResult(T mockedDbContext, int expectedResult) { mockedDbContext.AddExecuteSqlInterpolatedResult(expectedResult); } public override void AddExecuteSqlInterpolatedResult(T mockedDbContext, FormattableString sql, int expectedResult) { mockedDbContext.AddExecuteSqlInterpolatedResult(sql, expectedResult); } public override void AddExecuteSqlInterpolatedResult(T mockedDbContext, string sql, IEnumerable parameters, int expectedResult) { mockedDbContext.AddExecuteSqlInterpolatedResult(sql, parameters, expectedResult); } public override void AddExecuteSqlRawResult(T mockedDbContext, int expectedResult) { mockedDbContext.AddExecuteSqlRawResult(expectedResult); } public override void AddExecuteSqlRawResult(T mockedDbContext, string sql, int expectedResult) { mockedDbContext.AddExecuteSqlRawResult(sql, expectedResult); } public override void AddExecuteSqlRawResult(T mockedDbContext, string sql, IEnumerable parameters, int expectedResult) { mockedDbContext.AddExecuteSqlRawResult(sql, parameters, expectedResult); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Moq.Tests/BaseForDbQueryTests.cs ================================================ using System; using System.Collections.Generic; using EntityFrameworkCore.Testing.Common.Tests; using EntityFrameworkCore.Testing.Moq.Extensions; using Microsoft.EntityFrameworkCore; using NUnit.Framework; namespace EntityFrameworkCore.Testing.Moq.Tests { public abstract class BaseForDbQueryTests : BaseForReadOnlyDbSetTests where T : BaseTestEntity { protected TestDbContext MockedDbContext; [SetUp] public override void SetUp() { base.SetUp(); MockedDbContext = Create.MockedDbContextFor(); } protected override void AddFromSqlRawResult(DbSet mockedDbSet, IEnumerable expectedResult) { mockedDbSet.AddFromSqlRawResult(expectedResult); } protected override void AddFromSqlRawResult(DbSet mockedDbSet, string sql, IEnumerable expectedResult) { mockedDbSet.AddFromSqlRawResult(sql, expectedResult); } protected override void AddFromSqlRawResult(DbSet mockedDbSet, string sql, IEnumerable parameters, IEnumerable expectedResult) { mockedDbSet.AddFromSqlRawResult(sql, parameters, expectedResult); } protected override void AddFromSqlInterpolatedResult(DbSet mockedDbSet, IEnumerable expectedResult) { mockedDbSet.AddFromSqlInterpolatedResult(expectedResult); } protected override void AddFromSqlInterpolatedResult(DbSet mockedDbSet, FormattableString sql, IEnumerable expectedResult) { mockedDbSet.AddFromSqlInterpolatedResult(sql, expectedResult); } protected override void AddFromSqlInterpolatedResult(DbSet mockedDbSet, string sql, IEnumerable parameters, IEnumerable expectedResult) { mockedDbSet.AddFromSqlInterpolatedResult(sql, parameters, expectedResult); } protected override void AddToReadOnlySource(DbSet mockedDbQuery, T item) { mockedDbQuery.AddToReadOnlySource(item); } protected override void AddRangeToReadOnlySource(DbSet mockedDbQuery, IEnumerable items) { mockedDbQuery.AddRangeToReadOnlySource(items); } protected override void ClearReadOnlySource(DbSet mockedDbQuery) { mockedDbQuery.ClearReadOnlySource(); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Moq.Tests/BaseForDbSetTests.cs ================================================ using System; using System.Collections.Generic; using EntityFrameworkCore.Testing.Common.Tests; using EntityFrameworkCore.Testing.Moq.Extensions; using Microsoft.EntityFrameworkCore; namespace EntityFrameworkCore.Testing.Moq.Tests { public abstract class BaseForDbSetTests : BaseForDbSetTests where T : BaseTestEntity { protected override TestDbContext CreateMockedDbContext() { return Create.MockedDbContextFor(); } protected override void AddFromSqlRawResult(DbSet mockedDbSet, IEnumerable expectedResult) { mockedDbSet.AddFromSqlRawResult(expectedResult); } protected override void AddFromSqlRawResult(DbSet mockedDbSet, string sql, IEnumerable expectedResult) { mockedDbSet.AddFromSqlRawResult(sql, expectedResult); } protected override void AddFromSqlRawResult(DbSet mockedDbSet, string sql, IEnumerable parameters, IEnumerable expectedResult) { mockedDbSet.AddFromSqlRawResult(sql, parameters, expectedResult); } protected override void AddFromSqlInterpolatedResult(DbSet mockedDbSet, IEnumerable expectedResult) { mockedDbSet.AddFromSqlInterpolatedResult(expectedResult); } protected override void AddFromSqlInterpolatedResult(DbSet mockedDbSet, FormattableString sql, IEnumerable expectedResult) { mockedDbSet.AddFromSqlInterpolatedResult(sql, expectedResult); } protected override void AddFromSqlInterpolatedResult(DbSet mockedDbSet, string sql, IEnumerable parameters, IEnumerable expectedResult) { mockedDbSet.AddFromSqlInterpolatedResult(sql, parameters, expectedResult); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Moq.Tests/ByPropertyDbSetTests.cs ================================================ using System.Linq; using EntityFrameworkCore.Testing.Common.Tests; namespace EntityFrameworkCore.Testing.Moq.Tests { public class ByPropertyDbSetTests : BaseForDbSetTests { protected override IQueryable Queryable => MockedDbContext.TestEntities; } } ================================================ FILE: src/EntityFrameworkCore.Testing.Moq.Tests/ByPropertyReadOnlyDbSetExceptionTests.cs ================================================ using EntityFrameworkCore.Testing.Common.Tests; using Microsoft.EntityFrameworkCore; using NUnit.Framework; namespace EntityFrameworkCore.Testing.Moq.Tests { public class ByPropertyReadOnlyDbSetExceptionTests : ReadOnlyDbSetExceptionTests { protected TestDbContext MockedDbContext; protected override DbSet DbSet => MockedDbContext.TestReadOnlyEntities; [SetUp] public override void SetUp() { base.SetUp(); MockedDbContext = Create.MockedDbContextFor(); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Moq.Tests/ByPropertyReadOnlyDbSetTests.cs ================================================ using System.Linq; using EntityFrameworkCore.Testing.Common.Tests; namespace EntityFrameworkCore.Testing.Moq.Tests { public class ByPropertyReadOnlyDbSetTests : BaseForDbQueryTests { protected override IQueryable Queryable => MockedDbContext.Set(); } } ================================================ FILE: src/EntityFrameworkCore.Testing.Moq.Tests/ByTypeDbSetTests.cs ================================================ using System.Linq; using System.Linq.Expressions; using EntityFrameworkCore.Testing.Common.Tests; using Moq; using NUnit.Framework; namespace EntityFrameworkCore.Testing.Moq.Tests { public class ByTypeDbSetTests : BaseForDbSetTests { protected override IQueryable Queryable => MockedDbContext.Set(); [Test(Description = "This test ensures that method invoked via CallBase = true are verifiable")] public override void Select_ReturnsSequence() { base.Select_ReturnsSequence(); var queryProviderMock = Mock.Get(Queryable.Provider); queryProviderMock.Verify(m => m.CreateQuery(It.IsAny()), Times.Exactly(2)); queryProviderMock.Verify(m => m.CreateQuery(It.Is(mce => mce.Method.Name.Equals(nameof(System.Linq.Queryable.Select)))), Times.Exactly(2)); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Moq.Tests/ByTypeReadOnlyDbSetExceptionTests.cs ================================================ using EntityFrameworkCore.Testing.Common.Tests; using Microsoft.EntityFrameworkCore; using NUnit.Framework; namespace EntityFrameworkCore.Testing.Moq.Tests { public class ByTypeReadOnlyDbSetExceptionTests : ReadOnlyDbSetExceptionTests { protected TestDbContext MockedDbContext; protected override DbSet DbSet => MockedDbContext.Set(); [SetUp] public override void SetUp() { base.SetUp(); MockedDbContext = Create.MockedDbContextFor(); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Moq.Tests/ByTypeReadOnlyDbSetTests.cs ================================================ using System.Linq; using EntityFrameworkCore.Testing.Common.Tests; namespace EntityFrameworkCore.Testing.Moq.Tests { public class ByTypeReadOnlyDbSetTests : BaseForDbQueryTests { protected override IQueryable Queryable => MockedDbContext.Set(); } } ================================================ FILE: src/EntityFrameworkCore.Testing.Moq.Tests/CreateFactoryTests.cs ================================================ using System; using System.Linq; using Castle.DynamicProxy; using EntityFrameworkCore.Testing.Common.Tests; using Microsoft.EntityFrameworkCore; using NUnit.Framework; namespace EntityFrameworkCore.Testing.Moq.Tests { public class CreateFactoryTests : BaseForTests { [Test] public void CreateMockedDbContextFor_Type_CreatesMockedDbContext() { var mocked = Create.MockedDbContextFor(); Assert.Multiple(() => { Assert.That(mocked, Is.Not.Null); Assert.That(ProxyUtil.IsProxy(mocked), Is.True); }); } [Test] public void CreateMockedQueryProviderFor_Queryable_CreatesMockedQueryProvider() { var dbContextToMock = new TestDbContext(new DbContextOptionsBuilder().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options); var mocked = Create.MockedQueryProviderFor(dbContextToMock.TestEntities); Assert.Multiple(() => { Assert.That(mocked, Is.Not.Null); Assert.That(ProxyUtil.IsProxy(mocked), Is.True); }); } [Test] public void CreateMockedQueryProviderFor_NullQueryable_ThrowsException() { Assert.Throws(() => { var mocked = Create.MockedQueryProviderFor((IQueryable) null); }); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Moq.Tests/DbContextTestsUsingConstructorParameters.cs ================================================ using System; using EntityFrameworkCore.Testing.Common.Tests; using Microsoft.EntityFrameworkCore; using NUnit.Framework; namespace EntityFrameworkCore.Testing.Moq.Tests { public class DbContextTestsUsingConstructorParameters : BaseForDbContextTests { [SetUp] public override void SetUp() { base.SetUp(); MockedDbContext = Create.MockedDbContextFor(new DbContextOptionsBuilder().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Moq.Tests/DbContextTestsUsingType.cs ================================================ using EntityFrameworkCore.Testing.Common.Tests; using NUnit.Framework; namespace EntityFrameworkCore.Testing.Moq.Tests { public class DbContextTestsUsingType : BaseForDbContextTests { [SetUp] public override void SetUp() { base.SetUp(); MockedDbContext = Create.MockedDbContextFor(); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Moq.Tests/EntityFrameworkCore.Testing.Moq.Tests.csproj ================================================ net10.0 false NU1605 true NU1605 runtime; build; native; contentfiles; analyzers; buildtransitive all all runtime; build; native; contentfiles; analyzers; buildtransitive ================================================ FILE: src/EntityFrameworkCore.Testing.Moq.Tests/Issue114Tests.cs ================================================ namespace EntityFrameworkCore.Testing.Moq.Tests { public class Issue114Tests : Common.Tests.Issue114Tests { protected override TestDbContext MockedDbContextFactory() { return Create.MockedDbContextFor(); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Moq.Tests/Issue117Tests.cs ================================================ namespace EntityFrameworkCore.Testing.Moq.Tests { public class Issue117Tests : Common.Tests.Issue117Tests { protected override TestDbContext MockedDbContextFactory() { return Create.MockedDbContextFor(); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Moq.Tests/Issue126Tests.cs ================================================ using System; using EntityFrameworkCore.Testing.Common.Tests; using Microsoft.EntityFrameworkCore; using NUnit.Framework; namespace EntityFrameworkCore.Testing.Moq.Tests { public class Issue126Tests : Issue126Tests { [SetUp] public override void SetUp() { base.SetUp(); var options = new DbContextOptionsBuilder() .UseInMemoryDatabase(Guid.NewGuid().ToString()) .Options; DbContextFactory = () => Create.MockedDbContextFor(options); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Moq.Tests/Issue1Tests.cs ================================================ using System; using System.Data; using Microsoft.Data.SqlClient; using System.Linq; using System.Threading.Tasks; using AutoFixture; using Castle.DynamicProxy; using EntityFrameworkCore.Testing.Common.Tests; using EntityFrameworkCore.Testing.Moq.Extensions; using Microsoft.EntityFrameworkCore; using NUnit.Framework; namespace EntityFrameworkCore.Testing.Moq.Tests { public class Issue1Tests : BaseForTests { [Test] public void CreateMockedDbContextFor_ParametersForSpecificConstructor_CreatesSubstitute() { var mockedDbContext = Create.MockedDbContextFor(new DbContextOptionsBuilder().UseInMemoryDatabase(Guid.NewGuid().ToString()) .EnableSensitiveDataLogging() .Options); Assert.Multiple(() => { Assert.That(mockedDbContext, Is.Not.Null); Assert.That(ProxyUtil.IsProxy(mockedDbContext), Is.True); }); } [Test] public async Task ExecuteSqlRawAsync_SpecifiedSqlAndSqlParameter_ReturnsExpectedResultAndSetsOutputParameterValue() { var expectedResult = Fixture.Create(); var mockedDbContext = Create.MockedDbContextFor(); mockedDbContext.AddExecuteSqlRawResult(-1, (sql, parameters) => { ((SqlParameter) parameters.ElementAt(0)).Value = expectedResult; }); var outputParameter = new SqlParameter("OutputParameter", SqlDbType.NVarChar, 255) { Direction = ParameterDirection.Output }; var result = await mockedDbContext.Database.ExecuteSqlRawAsync(@"EXEC [StoredProcedureWithOutputParameter] @OutputParameter = @Result OUTPUT", outputParameter); Assert.Multiple(() => { Assert.That(result, Is.EqualTo(-1)); Assert.That(outputParameter.Value.ToString(), Is.EqualTo(expectedResult)); }); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Moq.Tests/Issue49Tests.cs ================================================ using EntityFrameworkCore.Testing.Common.Tests; using NUnit.Framework; namespace EntityFrameworkCore.Testing.Moq.Tests { public class Issue49Tests : Issue49Tests { [SetUp] public override void SetUp() { base.SetUp(); DbContext = Create.MockedDbContextFor(); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Moq.Tests/Issue4Tests.cs ================================================ using System; using System.Linq; using System.Threading.Tasks; using AutoFixture; using EntityFrameworkCore.Testing.Common.Tests; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Query; using NUnit.Framework; namespace EntityFrameworkCore.Testing.Moq.Tests { public class Issue4Tests : BaseForTests { [Test] public void AsQueryable_Set_ReturnsIQueryableOfTWithMockedQueryProvider() { var mockedDbContext = Create.MockedDbContextFor(); var mockedSetAsQueryable = mockedDbContext.TestEntities.AsQueryable(); var asyncProvider = mockedSetAsQueryable.Provider as IAsyncQueryProvider; Assert.That(asyncProvider, Is.Not.Null); } [Test] public async Task AsQueryableThenWhereThenSingleOrDefaultAsync_WhereOperationReturnsFalse_ReturnsDefault() { var entities = Fixture.CreateMany().ToList(); var mockedDbContext = Create.MockedDbContextFor(); var mockedSet = mockedDbContext.TestEntities; mockedSet.AddRange(entities); mockedDbContext.SaveChanges(); var result = await mockedSet.AsQueryable().Where(x => x.Id.Equals(Guid.NewGuid())).SingleOrDefaultAsync(); Assert.That(result, Is.Null); } [Test] public async Task AsQueryableThenWhereThenSingleOrDefaultAsync_WhereOperationReturnsTrue_ReturnsSingleEntity() { var entities = Fixture.CreateMany().ToList(); var entityToFind = entities.ElementAt(1); var mockedDbContext = Create.MockedDbContextFor(); var mockedSet = mockedDbContext.TestEntities; mockedSet.AddRange(entities); mockedDbContext.SaveChanges(); var result = await mockedSet.AsQueryable().Where(x => x.Id.Equals(entityToFind.Id)).SingleOrDefaultAsync(); Assert.That(result, Is.EqualTo(entityToFind)); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Moq.Tests/Issue6Tests.cs ================================================ using System; using System.Collections.Generic; using AutoFixture; using EntityFrameworkCore.Testing.Common.Tests; using EntityFrameworkCore.Testing.Moq.Extensions; using Microsoft.EntityFrameworkCore; using NUnit.Framework; namespace EntityFrameworkCore.Testing.Moq.Tests { public class Issue6Tests : BaseForTests { private static IEnumerable FromSqlInterpolated_SpecifiedSqlWithNullParameters_TestCases { get { yield return new TestCaseData(null, null); yield return new TestCaseData(null, 1); yield return new TestCaseData(DateTime.Parse("21 May 2020 9:05 PM"), null); } } [TestCaseSource(nameof(FromSqlInterpolated_SpecifiedSqlWithNullParameters_TestCases))] public void FromSqlInterpolated_SpecifiedSqlWithNullParameters_ReturnsExpectedResult(DateTime? dateTimeValue, int? intValue) { var expectedResult = new List { Fixture.Create() }; var mockedDbContext = Create.MockedDbContextFor(); mockedDbContext.Set().AddFromSqlInterpolatedResult($"SELECT * FROM [SqlFunctionWithNullableParameters]({dateTimeValue}, {intValue})", expectedResult); var actualResult = mockedDbContext.Set().FromSqlInterpolated($"SELECT * FROM [SqlFunctionWithNullableParameters]({dateTimeValue}, {intValue})"); Assert.That(actualResult, Is.EqualTo(expectedResult)); } [Test] public void FromSqlInterpolated_SpecifiedSqlWithDbNullParameters_ReturnsExpectedResult() { var expectedResult = new List { Fixture.Create() }; var mockedDbContext = Create.MockedDbContextFor(); mockedDbContext.Set().AddFromSqlInterpolatedResult($"SELECT * FROM [SqlFunctionWithNullableParameters]({DBNull.Value}, {DBNull.Value})", expectedResult); var actualResult = mockedDbContext.Set().FromSqlInterpolated($"SELECT * FROM [SqlFunctionWithNullableParameters]({DBNull.Value}, {DBNull.Value})"); Assert.That(actualResult, Is.EqualTo(expectedResult)); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.Moq.Tests/Issue88Tests.cs ================================================ using System; using EntityFrameworkCore.Testing.Common.Tests; using Microsoft.EntityFrameworkCore; using NUnit.Framework; namespace EntityFrameworkCore.Testing.Moq.Tests { public class Issue88Tests : Issue88Tests { [SetUp] public override void SetUp() { base.SetUp(); var options = new DbContextOptionsBuilder() .UseInMemoryDatabase(Guid.NewGuid().ToString()) .Options; DbContextFactory = () => Create.MockedDbContextFor(options); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.NSubstitute/Create.cs ================================================ using System.Linq; using EntityFrameworkCore.Testing.NSubstitute.Extensions; using EntityFrameworkCore.Testing.NSubstitute.Helpers; using Microsoft.EntityFrameworkCore; using rgvlee.Core.Common.Helpers; namespace EntityFrameworkCore.Testing.NSubstitute { /// /// Factory for creating mocked instances. /// public static class Create { /// /// Creates a mocked db context. /// /// The db context type. /// /// The parameters that will be used to create the mocked db context and, if one is not provided, /// the in-memory context that the mocked db context will use for in-memory provider supported operations. /// /// A mocked db context. /// /// If you do not provide any constructor arguments this method attempt to create a TDbContext /// via a constructor with a single DbContextOptionsBuilder parameter or a parameterless constructor. /// public static TDbContext MockedDbContextFor(params object[] constructorParameters) where TDbContext : DbContext { return constructorParameters != null && constructorParameters.Any() ? new MockedDbContextBuilder().UseConstructorWithParameters(constructorParameters).MockedDbContext : new MockedDbContextBuilder().MockedDbContext; } /// /// Creates a mocked query provider. /// /// The queryable type. /// The query provider source. /// A mocked query provider. public static IQueryProvider MockedQueryProviderFor(IQueryable queryable) where T : class { EnsureArgument.IsNotNull(queryable, nameof(queryable)); return queryable.Provider.CreateMockedQueryProvider(queryable); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.NSubstitute/EntityFrameworkCore.Testing.NSubstitute.csproj ================================================ net10.0 rgvlee EntityFrameworkCore.Testing.NSubstitute.xml NU1605 EntityFrameworkCore.Testing.NSubstitute.xml true NU1605 ================================================ FILE: src/EntityFrameworkCore.Testing.NSubstitute/EntityFrameworkCore.Testing.NSubstitute.xml ================================================ EntityFrameworkCore.Testing.NSubstitute Factory for creating mocked instances. Creates a mocked db context. The db context type. The parameters that will be used to create the mocked db context and, if one is not provided, the in-memory context that the mocked db context will use for in-memory provider supported operations. A mocked db context. If you do not provide any constructor arguments this method attempt to create a TDbContext via a constructor with a single DbContextOptionsBuilder parameter or a parameterless constructor. Creates a mocked query provider. The queryable type. The query provider source. A mocked query provider. Extensions for db contexts. Sets up ExecuteSqlInterpolated invocations to return a specified result. The db context type. The mocked db context. The integer to return when ExecuteSqlInterpolated is invoked. Operations to perform after ExecuteSqlCommand is invoked. The mocked db context. Sets up ExecuteSqlInterpolated invocations containing a specified sql string to return a specified result. The db context type. The mocked db context. The ExecuteSqlInterpolated sql string. Set up supports case insensitive partial matches. The integer to return when ExecuteSqlInterpolated is invoked. Operations to perform after ExecuteSqlCommand is invoked. The mocked db context. Sets up ExecuteSqlInterpolated invocations containing a specified sql string to return a specified result. The db context type. The mocked db context. The ExecuteSqlInterpolated sql string. Set up supports case insensitive partial matches. The ExecuteSqlInterpolated parameters. Set up supports case insensitive partial parameter sequence matching. The integer to return when ExecuteSqlInterpolated is invoked. Operations to perform after ExecuteSqlCommand is invoked. The mocked db context. Sets up ExecuteSqlRaw invocations to return a specified result. The db context type. The mocked db context. The integer to return when ExecuteSqlRaw is invoked. Operations to perform after ExecuteSqlCommand is invoked. The mocked db context. Sets up ExecuteSqlRaw invocations containing a specified sql string and parameters to return a specified result. The db context type. The mocked db context. The ExecuteSqlRaw sql string. Set up supports case insensitive partial matches. The integer to return when ExecuteSqlRaw is invoked. Operations to perform after ExecuteSqlCommand is invoked. The mocked db context. Sets up ExecuteSqlRaw invocations containing a specified sql string and parameters to return a specified result. The db context type. The mocked db context. The ExecuteSqlRaw sql string. Set up supports case insensitive partial matches. The ExecuteSqlRaw parameters. Set up supports case insensitive partial parameter sequence matching. The integer to return when ExecuteSqlRaw is invoked. Operations to perform after ExecuteSqlCommand is invoked. The mocked db context. Extensions for db sets. Extensions for queryable collections. Sets up FromSqlInterpolated invocations to return a specified result. The queryable source type. The mocked queryable. The FromSqlInterpolated result. The mocked queryable. Sets up FromSqlInterpolated invocations to return a specified result. The queryable source type. The mocked queryable. The FromSqlInterpolated sql string. Set up supports case insensitive partial matches. The FromSqlInterpolated result. The mocked queryable. Sets up FromSqlInterpolated invocations to return a specified result. The queryable source type. The mocked queryable. The FromSqlInterpolated sql string. Set up supports case insensitive partial matches. The FromSqlInterpolated parameters. Set up supports case insensitive partial parameter sequence matching. The FromSqlInterpolated result. The mocked queryable. Sets up FromSqlRaw invocations to return a specified result. The queryable source type. The mocked queryable. The FromSqlRaw result. The mocked queryable. Sets up FromSqlRaw invocations containing a specified sql string to return a specified result. The queryable source type. The mocked queryable. The FromSqlRaw sql string. Set up supports case insensitive partial matches. The FromSqlRaw result. The mocked queryable. Sets up FromSqlRaw invocations containing a specified sql string and parameters to return a specified result. The queryable source type. The mocked queryable. The FromSqlRaw sql string. Set up supports case insensitive partial matches. The FromSqlRaw parameters. Set up supports case insensitive partial parameter sequence matching. The FromSqlRaw result. The mocked queryable. Extensions for collection query providers. Sets up FromSqlInterpolated invocations to return a specified result. The queryable source type. The mocked query provider. The FromSqlInterpolated result. The mocked queryable. Sets up FromSqlInterpolated invocations containing a specified sql string to return a specified result. The queryable source type. The mocked query provider. The FromSqlInterpolated sql string. Set up supports case insensitive partial matches. The FromSqlInterpolated result. The mocked queryable. Sets up FromSqlInterpolated invocations containing a specified sql string and parameters to return a specified result. The queryable source type. The mocked query provider. The FromSqlInterpolated sql string. Set up supports case insensitive partial matches. The FromSqlInterpolated parameters. Set up supports case insensitive partial parameter sequence matching. The sequence to return when FromSqlInterpolated is invoked. The mocked query provider. Sets up FromSqlRaw invocations to return a specified result. The queryable source type. The mocked query provider. The FromSqlRaw result. The mocked queryable. Sets up FromSqlRaw invocations containing a specified sql string to return a specified result. The queryable source type. The mocked query provider. The FromSqlRaw sql string. Set up supports case insensitive partial matches. The FromSqlRaw result. The mocked queryable. Sets up FromSqlRaw invocations containing a specified sql string and parameters to return a specified result. The queryable source type. The mocked query provider. The FromSqlRaw sql string. Set up supports case insensitive partial matches. The FromSqlRaw parameters. Set up supports case insensitive partial parameter sequence matching. The sequence to return when FromSqlRaw is invoked. The mocked query provider. Extensions for read-only db sets. Adds an item to the end of the mocked readonly db set source. The entity type. The mocked readonly db set. The item to be added to the end of the mocked readonly db set source. Adds the items of the specified sequence to the end of the mocked readonly db set source. The entity type. The mocked readonly db set. The sequence whose items should be added to the end of the mocked readonly db set source. Removes all items from the mocked readonly db set source. The entity type. The mocked readonly db set. The mocked db context builder. The db context type. Creates the mocked db context. A mocked db context. ================================================ FILE: src/EntityFrameworkCore.Testing.NSubstitute/Extensions/DbContextExtensions.cs ================================================ #pragma warning disable EF1001 // Internal EF Core API usage. using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using EntityFrameworkCore.Testing.Common.Helpers; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.Extensions.Logging; using NSubstitute; using rgvlee.Core.Common.Helpers; namespace EntityFrameworkCore.Testing.NSubstitute.Extensions { /// /// Extensions for db contexts. /// public static class DbContextExtensions { private static readonly ILogger Logger = LoggingHelper.CreateLogger(typeof(DbContextExtensions)); /// /// Sets up ExecuteSqlInterpolated invocations to return a specified result. /// /// The db context type. /// The mocked db context. /// The integer to return when ExecuteSqlInterpolated is invoked. /// Operations to perform after ExecuteSqlCommand is invoked. /// The mocked db context. public static TDbContext AddExecuteSqlInterpolatedResult( this TDbContext mockedDbContext, int executeSqlInterpolatedResult, Action> callback = null) where TDbContext : DbContext { EnsureArgument.IsNotNull(mockedDbContext, nameof(mockedDbContext)); return mockedDbContext.AddExecuteSqlRawResult(string.Empty, new List(), executeSqlInterpolatedResult, callback); } /// /// Sets up ExecuteSqlInterpolated invocations containing a specified sql string to return a specified result. /// /// The db context type. /// The mocked db context. /// The ExecuteSqlInterpolated sql string. Set up supports case insensitive partial matches. /// The integer to return when ExecuteSqlInterpolated is invoked. /// Operations to perform after ExecuteSqlCommand is invoked. /// The mocked db context. public static TDbContext AddExecuteSqlInterpolatedResult( this TDbContext mockedDbContext, FormattableString sql, int executeSqlInterpolatedResult, Action> callback = null) where TDbContext : DbContext { EnsureArgument.IsNotNull(mockedDbContext, nameof(mockedDbContext)); return mockedDbContext.AddExecuteSqlRawResult(sql.Format, sql.GetArguments(), executeSqlInterpolatedResult, callback); } /// /// Sets up ExecuteSqlInterpolated invocations containing a specified sql string to return a specified result. /// /// The db context type. /// The mocked db context. /// The ExecuteSqlInterpolated sql string. Set up supports case insensitive partial matches. /// The ExecuteSqlInterpolated parameters. Set up supports case insensitive partial parameter sequence matching. /// The integer to return when ExecuteSqlInterpolated is invoked. /// Operations to perform after ExecuteSqlCommand is invoked. /// The mocked db context. public static TDbContext AddExecuteSqlInterpolatedResult( this TDbContext mockedDbContext, string sql, IEnumerable parameters, int executeSqlInterpolatedResult, Action> callback = null) where TDbContext : DbContext { EnsureArgument.IsNotNull(mockedDbContext, nameof(mockedDbContext)); return mockedDbContext.AddExecuteSqlRawResult(sql, parameters, executeSqlInterpolatedResult, callback); } /// /// Sets up ExecuteSqlRaw invocations to return a specified result. /// /// The db context type. /// The mocked db context. /// The integer to return when ExecuteSqlRaw is invoked. /// Operations to perform after ExecuteSqlCommand is invoked. /// The mocked db context. public static TDbContext AddExecuteSqlRawResult(this TDbContext mockedDbContext, int executeSqlRawResult, Action> callback = null) where TDbContext : DbContext { EnsureArgument.IsNotNull(mockedDbContext, nameof(mockedDbContext)); return mockedDbContext.AddExecuteSqlRawResult(string.Empty, new List(), executeSqlRawResult, callback); } /// /// Sets up ExecuteSqlRaw invocations containing a specified sql string and parameters to return a specified result. /// /// The db context type. /// The mocked db context. /// The ExecuteSqlRaw sql string. Set up supports case insensitive partial matches. /// The integer to return when ExecuteSqlRaw is invoked. /// Operations to perform after ExecuteSqlCommand is invoked. /// The mocked db context. public static TDbContext AddExecuteSqlRawResult( this TDbContext mockedDbContext, string sql, int executeSqlRawResult, Action> callback = null) where TDbContext : DbContext { EnsureArgument.IsNotNull(mockedDbContext, nameof(mockedDbContext)); return mockedDbContext.AddExecuteSqlRawResult(sql, new List(), executeSqlRawResult, callback); } /// /// Sets up ExecuteSqlRaw invocations containing a specified sql string and parameters to return a specified result. /// /// The db context type. /// The mocked db context. /// The ExecuteSqlRaw sql string. Set up supports case insensitive partial matches. /// The ExecuteSqlRaw parameters. Set up supports case insensitive partial parameter sequence matching. /// The integer to return when ExecuteSqlRaw is invoked. /// Operations to perform after ExecuteSqlCommand is invoked. /// The mocked db context. public static TDbContext AddExecuteSqlRawResult( this TDbContext mockedDbContext, string sql, IEnumerable parameters, int executeSqlRawResult, Action> callback = null) where TDbContext : DbContext { EnsureArgument.IsNotNull(mockedDbContext, nameof(mockedDbContext)); EnsureArgument.IsNotNull(sql, nameof(sql)); EnsureArgument.IsNotNull(parameters, nameof(parameters)); var relationalCommand = Substitute.For(); relationalCommand.ExecuteNonQuery(Arg.Any()).Returns(callInfo => executeSqlRawResult); relationalCommand.ExecuteNonQueryAsync(Arg.Any(), Arg.Any()) .Returns(callInfo => Task.FromResult(executeSqlRawResult)); var rawSqlCommand = Substitute.For(relationalCommand, new Dictionary()); rawSqlCommand.RelationalCommand.Returns(callInfo => relationalCommand); rawSqlCommand.ParameterValues.Returns(callInfo => new Dictionary()); var existingRawSqlCommandBuilder = ((IRelationalDatabaseFacadeDependencies) ((IInfrastructure) mockedDbContext).Instance.GetService(typeof(IDatabaseFacadeDependencies))) .RawSqlCommandBuilder; existingRawSqlCommandBuilder.Build( Arg.Is(s => s.Contains(sql, StringComparison.OrdinalIgnoreCase)), Arg.Is>(p => ParameterMatchingHelper.DoInvocationParametersMatchSetUpParameters(parameters, p)), Arg.Any()) .Returns(callInfo => rawSqlCommand) .AndDoes(callInfo => { var providedSql = callInfo.Arg(); var providedParameters = callInfo.Arg>(); callback?.Invoke(providedSql, providedParameters); var parts = new List(); parts.Add($"Invocation sql: {providedSql}"); parts.Add("Invocation Parameters:"); parts.Add(ParameterMatchingHelper.StringifyParameters(providedParameters)); Logger.LogDebug(string.Join(Environment.NewLine, parts)); }); return mockedDbContext; } } } ================================================ FILE: src/EntityFrameworkCore.Testing.NSubstitute/Extensions/DbSetExtensions.Internal.cs ================================================ using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Threading; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using NSubstitute; using rgvlee.Core.Common.Helpers; namespace EntityFrameworkCore.Testing.NSubstitute.Extensions { /// /// Extensions for db sets. /// public static class DbSetExtensions { internal static DbSet CreateMockedDbSet(this DbSet dbSet) where TEntity : class { EnsureArgument.IsNotNull(dbSet, nameof(dbSet)); var mockedDbSet = (DbSet) Substitute.For(new[] { typeof(DbSet), typeof(IAsyncEnumerable), typeof(IEnumerable), typeof(IEnumerable), typeof(IInfrastructure), typeof(IListSource), typeof(IQueryable) }, new object[] { }); var mockedQueryProvider = ((IQueryable) dbSet).Provider.CreateMockedQueryProvider(dbSet); mockedDbSet.Add(Arg.Any()).Returns(callInfo => dbSet.Add(callInfo.Arg())); mockedDbSet.AddAsync(Arg.Any(), Arg.Any()).Returns(callInfo => dbSet.AddAsync(callInfo.Arg(), callInfo.Arg())); mockedDbSet.When(x => x.AddRange(Arg.Any>())).Do(callInfo => dbSet.AddRange(callInfo.Arg>())); mockedDbSet.When(x => x.AddRange(Arg.Any())).Do(callInfo => dbSet.AddRange(callInfo.Arg())); mockedDbSet.AddRangeAsync(Arg.Any>(), Arg.Any()) .Returns(callInfo => dbSet.AddRangeAsync(callInfo.Arg>(), callInfo.Arg())); mockedDbSet.AddRangeAsync(Arg.Any()).Returns(callInfo => dbSet.AddRangeAsync(callInfo.Arg())); mockedDbSet.Attach(Arg.Any()).Returns(callInfo => dbSet.Attach(callInfo.Arg())); mockedDbSet.When(x => x.AttachRange(Arg.Any>())).Do(callInfo => dbSet.AttachRange(callInfo.Arg>())); mockedDbSet.When(x => x.AttachRange(Arg.Any())).Do(callInfo => dbSet.AttachRange(callInfo.Arg())); ((IListSource) mockedDbSet).ContainsListCollection.Returns(callInfo => ((IListSource) dbSet).ContainsListCollection); ((IQueryable) mockedDbSet).ElementType.Returns(callInfo => ((IQueryable) dbSet).ElementType); mockedDbSet.EntityType.Returns(callInfo => dbSet.EntityType); ((IQueryable) mockedDbSet).Expression.Returns(callInfo => ((IQueryable) dbSet).Expression); mockedDbSet.Find(Arg.Any()).Returns(callInfo => dbSet.Find(callInfo.Arg())); mockedDbSet.FindAsync(Arg.Any()).Returns(callInfo => dbSet.FindAsync(callInfo.Arg())); mockedDbSet.FindAsync(Arg.Any(), Arg.Any()) .Returns(callInfo => dbSet.FindAsync(callInfo.Arg(), callInfo.Arg())); ((IAsyncEnumerable) mockedDbSet).GetAsyncEnumerator(Arg.Any()) .Returns(callInfo => ((IAsyncEnumerable) dbSet).GetAsyncEnumerator(callInfo.Arg())); ((IEnumerable) mockedDbSet).GetEnumerator().Returns(callInfo => ((IEnumerable) dbSet).GetEnumerator()); ((IEnumerable) mockedDbSet).GetEnumerator().Returns(callInfo => ((IEnumerable) dbSet).GetEnumerator()); /* * System.NotSupportedException : Data binding directly to a store query is not supported. Instead populate a DbSet with data, * 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 * databound control iterates the data. For WPF bind to 'DbSet.Local.ToObservableCollection()'. For WinForms bind to * 'DbSet.Local.ToBindingList()'. For ASP.NET WebForms bind to 'DbSet.ToList()' or use Model Binding. */ ((IListSource) mockedDbSet).GetList().Returns(callInfo => dbSet.ToList()); ((IInfrastructure) mockedDbSet).Instance.Returns(callInfo => ((IInfrastructure) dbSet).Instance); mockedDbSet.Local.Returns(callInfo => dbSet.Local); mockedDbSet.Remove(Arg.Any()).Returns(callInfo => dbSet.Remove(callInfo.Arg())); mockedDbSet.When(x => x.RemoveRange(Arg.Any>())).Do(callInfo => dbSet.RemoveRange(callInfo.Arg>())); mockedDbSet.When(x => x.RemoveRange(Arg.Any())).Do(callInfo => dbSet.RemoveRange(callInfo.Arg())); mockedDbSet.Update(Arg.Any()).Returns(callInfo => dbSet.Update(callInfo.Arg())); mockedDbSet.When(x => x.UpdateRange(Arg.Any>())).Do(callInfo => dbSet.UpdateRange(callInfo.Arg>())); mockedDbSet.When(x => x.UpdateRange(Arg.Any())).Do(callInfo => dbSet.UpdateRange(callInfo.Arg())); ((IQueryable) mockedDbSet).Provider.Returns(callInfo => mockedQueryProvider); mockedDbSet.AsAsyncEnumerable().Returns(callInfo => dbSet.AsAsyncEnumerable()); mockedDbSet.AsQueryable().Returns(callInfo => dbSet); return mockedDbSet; } } } ================================================ FILE: src/EntityFrameworkCore.Testing.NSubstitute/Extensions/QueryProviderExtensions.Internal.cs ================================================ using System.Collections.Generic; using System.Linq; using EntityFrameworkCore.Testing.Common; using NSubstitute; using NSubstitute.Extensions; using rgvlee.Core.Common.Helpers; namespace EntityFrameworkCore.Testing.NSubstitute.Extensions { public static partial class QueryProviderExtensions { internal static IQueryProvider CreateMockedQueryProvider(this IQueryProvider queryProviderToMock, IEnumerable collection) where T : class { EnsureArgument.IsNotNull(queryProviderToMock, nameof(queryProviderToMock)); EnsureArgument.IsNotNull(collection, nameof(collection)); var mockedQueryProvider = Substitute.ForPartsOf>(collection); return mockedQueryProvider; } internal static void SetSource(this AsyncQueryProvider mockedQueryProvider, IEnumerable source) where T : class { EnsureArgument.IsNotNull(mockedQueryProvider, nameof(mockedQueryProvider)); EnsureArgument.IsNotNull(source, nameof(source)); mockedQueryProvider.Source = source.AsQueryable(); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.NSubstitute/Extensions/QueryProviderExtensions.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using EntityFrameworkCore.Testing.Common; using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.Extensions.Logging; using NSubstitute; using NSubstitute.Extensions; using rgvlee.Core.Common.Helpers; using ProjectExpressionHelper = EntityFrameworkCore.Testing.Common.Helpers.ExpressionHelper; namespace EntityFrameworkCore.Testing.NSubstitute.Extensions { /// /// Extensions for collection query providers. /// public static partial class QueryProviderExtensions { private static readonly ILogger Logger = LoggingHelper.CreateLogger(typeof(QueryProviderExtensions)); /// /// Sets up FromSqlInterpolated invocations to return a specified result. /// /// The queryable source type. /// The mocked query provider. /// The FromSqlInterpolated result. /// The mocked queryable. public static IQueryProvider AddFromSqlInterpolatedResult(this IQueryProvider mockedQueryProvider, IEnumerable fromSqlInterpolatedResult) where T : class { EnsureArgument.IsNotNull(mockedQueryProvider, nameof(mockedQueryProvider)); mockedQueryProvider.AddFromSqlRawResult(string.Empty, new List(), fromSqlInterpolatedResult); return mockedQueryProvider; } /// /// Sets up FromSqlInterpolated invocations containing a specified sql string to return a specified result. /// /// The queryable source type. /// The mocked query provider. /// The FromSqlInterpolated sql string. Set up supports case insensitive partial matches. /// The FromSqlInterpolated result. /// The mocked queryable. public static IQueryProvider AddFromSqlInterpolatedResult(this IQueryProvider mockedQueryProvider, FormattableString sql, IEnumerable fromSqlInterpolatedResult) where T : class { EnsureArgument.IsNotNull(mockedQueryProvider, nameof(mockedQueryProvider)); mockedQueryProvider.AddFromSqlRawResult(sql.Format, sql.GetArguments(), fromSqlInterpolatedResult); return mockedQueryProvider; } /// /// Sets up FromSqlInterpolated invocations containing a specified sql string and parameters to return a specified result. /// /// The queryable source type. /// The mocked query provider. /// The FromSqlInterpolated sql string. Set up supports case insensitive partial matches. /// The FromSqlInterpolated parameters. Set up supports case insensitive partial parameter sequence matching. /// The sequence to return when FromSqlInterpolated is invoked. /// The mocked query provider. public static IQueryProvider AddFromSqlInterpolatedResult( this IQueryProvider mockedQueryProvider, string sql, IEnumerable parameters, IEnumerable fromSqlInterpolatedResult) where T : class { EnsureArgument.IsNotNull(mockedQueryProvider, nameof(mockedQueryProvider)); mockedQueryProvider.AddFromSqlRawResult(sql, parameters, fromSqlInterpolatedResult); return mockedQueryProvider; } /// /// Sets up FromSqlRaw invocations to return a specified result. /// /// The queryable source type. /// The mocked query provider. /// The FromSqlRaw result. /// The mocked queryable. public static IQueryProvider AddFromSqlRawResult(this IQueryProvider mockedQueryProvider, IEnumerable fromSqlRawResult) where T : class { EnsureArgument.IsNotNull(mockedQueryProvider, nameof(mockedQueryProvider)); mockedQueryProvider.AddFromSqlRawResult(string.Empty, new List(), fromSqlRawResult); return mockedQueryProvider; } /// /// Sets up FromSqlRaw invocations containing a specified sql string to return a specified result. /// /// The queryable source type. /// The mocked query provider. /// The FromSqlRaw sql string. Set up supports case insensitive partial matches. /// The FromSqlRaw result. /// The mocked queryable. public static IQueryProvider AddFromSqlRawResult(this IQueryProvider mockedQueryProvider, string sql, IEnumerable fromSqlRawResult) where T : class { EnsureArgument.IsNotNull(mockedQueryProvider, nameof(mockedQueryProvider)); mockedQueryProvider.AddFromSqlRawResult(sql, new List(), fromSqlRawResult); return mockedQueryProvider; } /// /// Sets up FromSqlRaw invocations containing a specified sql string and parameters to return a specified result. /// /// The queryable source type. /// The mocked query provider. /// The FromSqlRaw sql string. Set up supports case insensitive partial matches. /// The FromSqlRaw parameters. Set up supports case insensitive partial parameter sequence matching. /// The sequence to return when FromSqlRaw is invoked. /// The mocked query provider. public static IQueryProvider AddFromSqlRawResult(this IQueryProvider mockedQueryProvider, string sql, IEnumerable parameters, IEnumerable fromSqlResult) where T : class { EnsureArgument.IsNotNull(mockedQueryProvider, nameof(mockedQueryProvider)); EnsureArgument.IsNotNull(sql, nameof(sql)); EnsureArgument.IsNotNull(parameters, nameof(parameters)); EnsureArgument.IsNotNull(fromSqlResult, nameof(fromSqlResult)); Logger.LogDebug("Setting up '{sql}'", sql); var createQueryResult = new AsyncEnumerable(fromSqlResult); mockedQueryProvider.Configure() .CreateQuery(Arg.Is(fsqre => ProjectExpressionHelper.SqlAndParametersMatchFromSqlExpression(sql, parameters, fsqre))) .Returns(callInfo => { ProjectExpressionHelper.ThrowIfExpressionIsNotSupported(callInfo.Arg()); var fsqre = (FromSqlQueryRootExpression) callInfo.Arg(); var parts = new List(); parts.Add("FromSql inputs:"); parts.Add(ProjectExpressionHelper.StringifyFromSqlExpression(fsqre)); Logger.LogDebug(string.Join(Environment.NewLine, parts)); return createQueryResult; }); return mockedQueryProvider; } } } ================================================ FILE: src/EntityFrameworkCore.Testing.NSubstitute/Extensions/QueryableExtensions.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using rgvlee.Core.Common.Helpers; namespace EntityFrameworkCore.Testing.NSubstitute.Extensions { /// /// Extensions for queryable collections. /// public static class QueryableExtensions { /// /// Sets up FromSqlInterpolated invocations to return a specified result. /// /// The queryable source type. /// The mocked queryable. /// The FromSqlInterpolated result. /// The mocked queryable. public static IQueryable AddFromSqlInterpolatedResult(this IQueryable mockedQueryable, IEnumerable fromSqlInterpolatedResult) where T : class { EnsureArgument.IsNotNull(mockedQueryable, nameof(mockedQueryable)); mockedQueryable.Provider.AddFromSqlRawResult(string.Empty, new List(), fromSqlInterpolatedResult); return mockedQueryable; } /// /// Sets up FromSqlInterpolated invocations to return a specified result. /// /// The queryable source type. /// The mocked queryable. /// The FromSqlInterpolated sql string. Set up supports case insensitive partial matches. /// The FromSqlInterpolated result. /// The mocked queryable. public static IQueryable AddFromSqlInterpolatedResult(this IQueryable mockedQueryable, FormattableString sql, IEnumerable fromSqlInterpolatedResult) where T : class { EnsureArgument.IsNotNull(mockedQueryable, nameof(mockedQueryable)); mockedQueryable.Provider.AddFromSqlRawResult(sql.Format, sql.GetArguments(), fromSqlInterpolatedResult); return mockedQueryable; } /// /// Sets up FromSqlInterpolated invocations to return a specified result. /// /// The queryable source type. /// The mocked queryable. /// The FromSqlInterpolated sql string. Set up supports case insensitive partial matches. /// The FromSqlInterpolated parameters. Set up supports case insensitive partial parameter sequence matching. /// The FromSqlInterpolated result. /// The mocked queryable. public static IQueryable AddFromSqlInterpolatedResult( this IQueryable mockedQueryable, string sql, IEnumerable parameters, IEnumerable fromSqlInterpolatedResult) where T : class { EnsureArgument.IsNotNull(mockedQueryable, nameof(mockedQueryable)); mockedQueryable.Provider.AddFromSqlRawResult(sql, parameters, fromSqlInterpolatedResult); return mockedQueryable; } /// /// Sets up FromSqlRaw invocations to return a specified result. /// /// The queryable source type. /// The mocked queryable. /// The FromSqlRaw result. /// The mocked queryable. public static IQueryable AddFromSqlRawResult(this IQueryable mockedQueryable, IEnumerable fromSqlRawResult) where T : class { EnsureArgument.IsNotNull(mockedQueryable, nameof(mockedQueryable)); mockedQueryable.Provider.AddFromSqlRawResult(string.Empty, new List(), fromSqlRawResult); return mockedQueryable; } /// /// Sets up FromSqlRaw invocations containing a specified sql string to return a specified result. /// /// The queryable source type. /// The mocked queryable. /// The FromSqlRaw sql string. Set up supports case insensitive partial matches. /// The FromSqlRaw result. /// The mocked queryable. public static IQueryable AddFromSqlRawResult(this IQueryable mockedQueryable, string sql, IEnumerable fromSqlRawResult) where T : class { EnsureArgument.IsNotNull(mockedQueryable, nameof(mockedQueryable)); mockedQueryable.Provider.AddFromSqlRawResult(sql, new List(), fromSqlRawResult); return mockedQueryable; } /// /// Sets up FromSqlRaw invocations containing a specified sql string and parameters to return a specified result. /// /// The queryable source type. /// The mocked queryable. /// The FromSqlRaw sql string. Set up supports case insensitive partial matches. /// The FromSqlRaw parameters. Set up supports case insensitive partial parameter sequence matching. /// The FromSqlRaw result. /// The mocked queryable. public static IQueryable AddFromSqlRawResult(this IQueryable mockedQueryable, string sql, IEnumerable parameters, IEnumerable fromSqlRawResult) where T : class { EnsureArgument.IsNotNull(mockedQueryable, nameof(mockedQueryable)); mockedQueryable.Provider.AddFromSqlRawResult(sql, parameters, fromSqlRawResult); return mockedQueryable; } } } ================================================ FILE: src/EntityFrameworkCore.Testing.NSubstitute/Extensions/ReadOnlyDbSetExtensions.Internal.cs ================================================ using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Threading; using EntityFrameworkCore.Testing.Common; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Query; using NSubstitute; using NSubstitute.ExceptionExtensions; using rgvlee.Core.Common.Helpers; namespace EntityFrameworkCore.Testing.NSubstitute.Extensions { public static partial class ReadOnlyDbSetExtensions { internal static DbSet CreateMockedReadOnlyDbSet(this DbSet readOnlyDbSet) where TEntity : class { EnsureArgument.IsNotNull(readOnlyDbSet, nameof(readOnlyDbSet)); var mockedReadOnlyDbSet = (DbSet) Substitute.For(new[] { typeof(DbSet), typeof(IAsyncEnumerable), typeof(IEnumerable), typeof(IEnumerable), typeof(IInfrastructure), typeof(IListSource), typeof(IQueryable) }, new object[] { }); var asyncEnumerable = new AsyncEnumerable(new List(), new FakeQueryRootExpression(Substitute.For(), readOnlyDbSet.EntityType)); var mockedQueryProvider = ((IQueryable) readOnlyDbSet).Provider.CreateMockedQueryProvider(asyncEnumerable); var invalidOperationException = new InvalidOperationException( $"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."); mockedReadOnlyDbSet.Add(Arg.Any()).Throws(callInfo => invalidOperationException); mockedReadOnlyDbSet.AddAsync(Arg.Any(), Arg.Any()).Throws(callInfo => invalidOperationException); mockedReadOnlyDbSet.When(x => x.AddRange(Arg.Any>())).Do(callInfo => throw invalidOperationException); mockedReadOnlyDbSet.When(x => x.AddRange(Arg.Any())).Do(callInfo => throw invalidOperationException); mockedReadOnlyDbSet.AddRangeAsync(Arg.Any>(), Arg.Any()).Throws(callInfo => invalidOperationException); mockedReadOnlyDbSet.AddRangeAsync(Arg.Any()).Throws(callInfo => invalidOperationException); mockedReadOnlyDbSet.Attach(Arg.Any()).Throws(callInfo => invalidOperationException); mockedReadOnlyDbSet.When(x => x.AttachRange(Arg.Any>())).Do(callInfo => throw invalidOperationException); mockedReadOnlyDbSet.When(x => x.AttachRange(Arg.Any())).Do(callInfo => throw invalidOperationException); ((IListSource) mockedReadOnlyDbSet).ContainsListCollection.Returns(callInfo => false); ((IQueryable) mockedReadOnlyDbSet).ElementType.Returns(callInfo => asyncEnumerable.ElementType); mockedReadOnlyDbSet.EntityType.Returns(callInfo => readOnlyDbSet.EntityType); ((IQueryable) mockedReadOnlyDbSet).Expression.Returns(callInfo => asyncEnumerable.Expression); mockedReadOnlyDbSet.Find(Arg.Any()).Throws(callInfo => new InvalidOperationException($"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.")); mockedReadOnlyDbSet.FindAsync(Arg.Any()).Throws(callInfo => new InvalidOperationException($"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.")); mockedReadOnlyDbSet.FindAsync(Arg.Any(), Arg.Any()).Throws(callInfo => new InvalidOperationException($"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.")); ((IAsyncEnumerable) mockedReadOnlyDbSet).GetAsyncEnumerator(Arg.Any()) .Returns(callInfo => asyncEnumerable.GetAsyncEnumerator(callInfo.Arg())); ((IEnumerable) mockedReadOnlyDbSet).GetEnumerator().Returns(callInfo => ((IEnumerable) asyncEnumerable).GetEnumerator()); ((IEnumerable) mockedReadOnlyDbSet).GetEnumerator().Returns(callInfo => ((IEnumerable) asyncEnumerable).GetEnumerator()); ((IListSource) mockedReadOnlyDbSet).GetList().Returns(callInfo => asyncEnumerable.ToList()); ((IInfrastructure) mockedReadOnlyDbSet).Instance.Returns(callInfo => ((IInfrastructure) readOnlyDbSet).Instance); mockedReadOnlyDbSet.Local.Throws(callInfo => new InvalidOperationException($"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.")); mockedReadOnlyDbSet.Remove(Arg.Any()).Throws(callInfo => invalidOperationException); mockedReadOnlyDbSet.When(x => x.RemoveRange(Arg.Any>())).Do(callInfo => throw invalidOperationException); mockedReadOnlyDbSet.When(x => x.RemoveRange(Arg.Any())).Do(callInfo => throw invalidOperationException); mockedReadOnlyDbSet.Update(Arg.Any()).Throws(callInfo => invalidOperationException); mockedReadOnlyDbSet.When(x => x.UpdateRange(Arg.Any>())).Do(callInfo => throw invalidOperationException); mockedReadOnlyDbSet.When(x => x.UpdateRange(Arg.Any())).Do(callInfo => throw invalidOperationException); ((IQueryable) mockedReadOnlyDbSet).Provider.Returns(callInfo => mockedQueryProvider); mockedReadOnlyDbSet.AsAsyncEnumerable().Returns(callInfo => asyncEnumerable); mockedReadOnlyDbSet.AsQueryable().Returns(callInfo => asyncEnumerable); return mockedReadOnlyDbSet; } internal static void SetSource(this DbSet mockedReadOnlyDbSet, IEnumerable source) where TEntity : class { EnsureArgument.IsNotNull(mockedReadOnlyDbSet, nameof(mockedReadOnlyDbSet)); EnsureArgument.IsNotNull(source, nameof(source)); var asyncEnumerable = new AsyncEnumerable(source, new FakeQueryRootExpression(Substitute.For(), mockedReadOnlyDbSet.EntityType)); var mockedQueryProvider = ((IQueryable) mockedReadOnlyDbSet).Provider; ((IQueryable) mockedReadOnlyDbSet).Expression.Returns(callInfo => asyncEnumerable.Expression); ((IAsyncEnumerable) mockedReadOnlyDbSet).GetAsyncEnumerator(Arg.Any()) .Returns(callInfo => asyncEnumerable.GetAsyncEnumerator(callInfo.Arg())); ((IEnumerable) mockedReadOnlyDbSet).GetEnumerator().Returns(callInfo => ((IEnumerable) asyncEnumerable).GetEnumerator()); ((IEnumerable) mockedReadOnlyDbSet).GetEnumerator().Returns(callInfo => ((IEnumerable) asyncEnumerable).GetEnumerator()); ((IListSource) mockedReadOnlyDbSet).GetList().Returns(callInfo => asyncEnumerable.ToList()); mockedReadOnlyDbSet.AsAsyncEnumerable().Returns(callInfo => asyncEnumerable); mockedReadOnlyDbSet.AsQueryable().Returns(callInfo => asyncEnumerable); ((AsyncQueryProvider) mockedQueryProvider).SetSource(asyncEnumerable); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.NSubstitute/Extensions/ReadOnlyDbSetExtensions.cs ================================================ using System.Collections.Generic; using System.Linq; using Microsoft.EntityFrameworkCore; using rgvlee.Core.Common.Helpers; namespace EntityFrameworkCore.Testing.NSubstitute.Extensions { /// /// Extensions for read-only db sets. /// public static partial class ReadOnlyDbSetExtensions { /// /// Adds an item to the end of the mocked readonly db set source. /// /// The entity type. /// The mocked readonly db set. /// The item to be added to the end of the mocked readonly db set source. public static void AddToReadOnlySource(this DbSet mockedReadOnlyDbSet, TEntity item) where TEntity : class { EnsureArgument.IsNotNull(mockedReadOnlyDbSet, nameof(mockedReadOnlyDbSet)); EnsureArgument.IsNotNull(item, nameof(item)); var list = mockedReadOnlyDbSet.ToList(); list.Add(item); mockedReadOnlyDbSet.SetSource(list); } /// /// Adds the items of the specified sequence to the end of the mocked readonly db set source. /// /// The entity type. /// The mocked readonly db set. /// The sequence whose items should be added to the end of the mocked readonly db set source. public static void AddRangeToReadOnlySource(this DbSet mockedReadOnlyDbSet, IEnumerable items) where TEntity : class { EnsureArgument.IsNotNull(mockedReadOnlyDbSet, nameof(mockedReadOnlyDbSet)); EnsureArgument.IsNotEmpty(items, nameof(items)); var list = mockedReadOnlyDbSet.ToList(); list.AddRange(items); mockedReadOnlyDbSet.SetSource(list); } /// /// Removes all items from the mocked readonly db set source. /// /// The entity type. /// The mocked readonly db set. public static void ClearReadOnlySource(this DbSet mockedReadOnlyDbSet) where TEntity : class { EnsureArgument.IsNotNull(mockedReadOnlyDbSet, nameof(mockedReadOnlyDbSet)); mockedReadOnlyDbSet.SetSource(new List()); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.NSubstitute/Helpers/MockedDbContextBuilder.cs ================================================ using EntityFrameworkCore.Testing.Common.Helpers; using Microsoft.EntityFrameworkCore; namespace EntityFrameworkCore.Testing.NSubstitute.Helpers { /// /// The mocked db context builder. /// /// The db context type. public class MockedDbContextBuilder : BaseMockedDbContextBuilder where TDbContext : DbContext { /// /// Creates the mocked db context. /// /// A mocked db context. public override TDbContext MockedDbContext => new MockedDbContextFactory(Options).Create(); } } ================================================ FILE: src/EntityFrameworkCore.Testing.NSubstitute/Helpers/MockedDbContextFactory.Internal.cs ================================================ #pragma warning disable EF1001 // Internal EF Core API usage. using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Threading; using System.Threading.Tasks; using EntityFrameworkCore.Testing.Common.Helpers; using EntityFrameworkCore.Testing.NSubstitute.Extensions; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.Extensions.Logging; using NSubstitute; using NSubstitute.Core; using NSubstitute.ExceptionExtensions; using NSubstitute.Extensions; using NSubstitute.ReturnsExtensions; namespace EntityFrameworkCore.Testing.NSubstitute.Helpers { internal class MockedDbContextFactory : BaseMockedDbContextFactory where TDbContext : DbContext { public MockedDbContextFactory(MockedDbContextFactoryOptions options) : base(options) { } public override TDbContext Create() { var mockedDbContext = (TDbContext) Substitute.For(new[] { typeof(TDbContext), typeof(IDbContextDependencies), typeof(IDbSetCache), typeof(IInfrastructure), typeof(IDbContextPoolable) }, ConstructorParameters.ToArray()); var router = SubstitutionContext.Current.GetCallRouterFor(mockedDbContext); router.RegisterCustomCallHandlerFactory(state => new NoSetUpHandler(DbContext)); mockedDbContext.Add(Arg.Any()).Returns(callInfo => DbContext.Add(callInfo.Arg())); mockedDbContext.AddAsync(Arg.Any(), Arg.Any()) .Returns(callInfo => DbContext.AddAsync(callInfo.Arg(), callInfo.Arg())); mockedDbContext.When(x => x.AddRange(Arg.Any())).Do(callInfo => DbContext.AddRange(callInfo.Arg())); mockedDbContext.When(x => x.AddRange(Arg.Any>())).Do(callInfo => DbContext.AddRange(callInfo.Arg>())); mockedDbContext.AddRangeAsync(Arg.Any(), Arg.Any()) .Returns(callInfo => DbContext.AddRangeAsync(callInfo.Arg(), callInfo.Arg())); mockedDbContext.AddRangeAsync(Arg.Any>(), Arg.Any()) .Returns(callInfo => DbContext.AddRangeAsync(callInfo.Arg(), callInfo.Arg())); mockedDbContext.Attach(Arg.Any()).Returns(callInfo => DbContext.Attach(callInfo.Arg())); mockedDbContext.When(x => x.AttachRange(Arg.Any())).Do(callInfo => DbContext.AttachRange(callInfo.Arg())); mockedDbContext.When(x => x.AttachRange(Arg.Any>())).Do(callInfo => DbContext.AttachRange(callInfo.Arg>())); ((IDbContextDependencies) mockedDbContext).ChangeDetector.Returns(callInfo => ((IDbContextDependencies) DbContext).ChangeDetector); mockedDbContext.ChangeTracker.Returns(callInfo => DbContext.ChangeTracker); mockedDbContext.ContextId.Returns(callInfo => DbContext.ContextId); mockedDbContext.Database.Returns(callInfo => DbContext.Database); mockedDbContext.When(x => x.Dispose()).Do(callInfo => DbContext.Dispose()); mockedDbContext.DisposeAsync().Returns(callInfo => DbContext.DisposeAsync()); ((IDbContextDependencies) mockedDbContext).EntityFinderFactory.Returns(callInfo => ((IDbContextDependencies) DbContext).EntityFinderFactory); ((IDbContextDependencies) mockedDbContext).EntityGraphAttacher.Returns(callInfo => ((IDbContextDependencies) DbContext).EntityGraphAttacher); mockedDbContext.Entry(Arg.Any()).Returns(callInfo => DbContext.Entry(callInfo.Arg())); mockedDbContext.Find(Arg.Any(), Arg.Any()).Returns(callInfo => DbContext.Find(callInfo.Arg(), callInfo.Arg())); mockedDbContext.FindAsync(Arg.Any(), Arg.Any()).Returns(callInfo => DbContext.FindAsync(callInfo.Arg(), callInfo.Arg())); mockedDbContext.FindAsync(Arg.Any(), Arg.Any(), Arg.Any()) .Returns(callInfo => DbContext.FindAsync(callInfo.Arg(), callInfo.Arg(), callInfo.Arg())); ((IDbSetCache) mockedDbContext).GetOrAddSet(Arg.Any(), Arg.Any()) .Returns(callInfo => ((IDbSetCache) DbContext).GetOrAddSet(callInfo.Arg(), callInfo.Arg())); ((IDbContextDependencies) mockedDbContext).InfrastructureLogger.Returns(callInfo => ((IDbContextDependencies) DbContext).InfrastructureLogger); ((IInfrastructure) mockedDbContext).Instance.Returns(callInfo => ((IInfrastructure) DbContext).Instance); //((IDbContextDependencies) mockedDbContext).Model.Returns(callInfo => ((IDbContextDependencies) DbContext).Model); ((IDbContextDependencies) mockedDbContext).QueryProvider.Returns(callInfo => ((IDbContextDependencies) DbContext).QueryProvider); mockedDbContext.Remove(Arg.Any()).Returns(callInfo => DbContext.Remove(callInfo.Arg())); mockedDbContext.When(x => x.RemoveRange(Arg.Any())).Do(callInfo => DbContext.RemoveRange(callInfo.Arg())); mockedDbContext.When(x => x.RemoveRange(Arg.Any>())).Do(callInfo => DbContext.RemoveRange(callInfo.Arg>())); ((IDbContextPoolable) mockedDbContext).When(x => x.ResetState()).Do(callInfo => ((IDbContextPoolable) DbContext).ResetState()); ((IDbContextPoolable) mockedDbContext).When(x => x.ResetStateAsync(Arg.Any())) .Do(callInfo => ((IDbContextPoolable) DbContext).ResetStateAsync(callInfo.Arg())); // ((IDbContextPoolable) mockedDbContext).When(x => x.Resurrect(Arg.Any())) // .Do(callInfo => ((IDbContextPoolable) DbContext).Resurrect(callInfo.Arg())); mockedDbContext.SaveChanges().Returns(callInfo => DbContext.SaveChanges()); mockedDbContext.SaveChanges(Arg.Any()).Returns(callInfo => DbContext.SaveChanges(callInfo.Arg())); mockedDbContext.SaveChangesAsync(Arg.Any()).Returns(callInfo => DbContext.SaveChangesAsync(callInfo.Arg())); mockedDbContext.SaveChangesAsync(Arg.Any(), Arg.Any()) .Returns(callInfo => DbContext.SaveChangesAsync(callInfo.Arg(), callInfo.Arg())); // ((IDbContextPoolable) mockedDbContext).When(x => x.SetPool(Arg.Any())) // .Do(callInfo => ((IDbContextPoolable) DbContext).SetPool(callInfo.Arg())); ((IDbContextDependencies) mockedDbContext).SetSource.Returns(callInfo => ((IDbContextDependencies) DbContext).SetSource); // ((IDbContextPoolable) mockedDbContext).SnapshotConfiguration().Returns(callInfo => ((IDbContextPoolable) DbContext).SnapshotConfiguration()); ((IDbContextDependencies) mockedDbContext).StateManager.Returns(callInfo => ((IDbContextDependencies) DbContext).StateManager); mockedDbContext.Update(Arg.Any()).Returns(callInfo => DbContext.Update(callInfo.Arg())); ((IDbContextDependencies) mockedDbContext).UpdateLogger.Returns(callInfo => ((IDbContextDependencies) DbContext).UpdateLogger); mockedDbContext.When(x => x.UpdateRange(Arg.Any())).Do(callInfo => DbContext.UpdateRange(callInfo.Arg())); mockedDbContext.When(x => x.UpdateRange(Arg.Any>())).Do(callInfo => DbContext.UpdateRange(callInfo.Arg>())); //Relational set up var rawSqlCommandBuilder = Substitute.For(); rawSqlCommandBuilder.Build(Arg.Any(), Arg.Any>(), Arg.Any()) .Throws(callInfo => { Logger.LogDebug("Catch all exception invoked"); return new InvalidOperationException(); }); // var concurrencyDetector = Substitute.For(); // concurrencyDetector.EnterCriticalSection().Returns(callInfo => new ConcurrencyDetectorCriticalSectionDisposer(Substitute.For())); var relationalConnection = Substitute.For(); relationalConnection.CommandTimeout.Returns(callInfo => 0); var dependencies = Substitute.For(); // dependencies.ConcurrencyDetector.Returns(callInfo => concurrencyDetector); dependencies.CommandLogger.Returns(callInfo => Substitute.For()); dependencies.RawSqlCommandBuilder.Returns(callInfo => rawSqlCommandBuilder); dependencies.RelationalConnection.Returns(callInfo => relationalConnection); var serviceProvider = Substitute.For(); serviceProvider.GetService(Arg.Is(t => t == typeof(IDatabaseFacadeDependencies))).Returns(callInfo => dependencies); serviceProvider.GetService(Arg.Is(t => t == typeof(IModel))).Returns(callInfo => Substitute.For()); ((IInfrastructure) mockedDbContext).Instance.Returns(callInfo => serviceProvider); var databaseFacade = Substitute.For(new[] { typeof(DatabaseFacade), typeof(IDatabaseFacadeDependenciesAccessor) }, new[] { mockedDbContext }); ((IDatabaseFacadeDependenciesAccessor) databaseFacade).Dependencies.Returns(callInfo => dependencies); ((DatabaseFacade)databaseFacade).BeginTransaction().Returns(callInfo => Substitute.For()); ((DatabaseFacade)databaseFacade).BeginTransactionAsync(Arg.Any()).Returns(callInfo => Task.FromResult(Substitute.For())); mockedDbContext.Database.Returns(callInfo => databaseFacade); return mockedDbContext; } } } ================================================ FILE: src/EntityFrameworkCore.Testing.NSubstitute/Helpers/NoSetUpHandler.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Threading; using EntityFrameworkCore.Testing.Common; using EntityFrameworkCore.Testing.NSubstitute.Extensions; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.Extensions.Logging; using NSubstitute; using NSubstitute.Core; using NSubstitute.Extensions; using rgvlee.Core.Common.Extensions; using rgvlee.Core.Common.Helpers; namespace EntityFrameworkCore.Testing.NSubstitute.Helpers { internal class NoSetUpHandler : ICallHandler where TDbContext : DbContext { private static readonly ILogger> Logger = LoggingHelper.CreateLogger>(); private readonly List _allModelEntityTypes; private readonly TDbContext _dbContext; private readonly List _dbContextModelProperties; public NoSetUpHandler(TDbContext dbContext) { _dbContext = dbContext; _allModelEntityTypes = _dbContext.Model.GetEntityTypes().ToList(); _dbContextModelProperties = _dbContext.GetType() .GetProperties() .Where(x => x.PropertyType.IsGenericType && x.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>)) .ToList(); } public RouteAction Handle(ICall call) { var mockedDbContext = call.Target(); var invokedMethod = call.GetMethodInfo(); var arguments = call.GetArguments(); var modelType = GetModelType(invokedMethod); if (modelType == null) { return invokedMethod.ReturnType != typeof(void) ? RouteAction.Return(invokedMethod.ReturnType.GetDefaultValue()) : RouteAction.Continue(); } Logger.LogDebug("Setting up model '{type}'", modelType); var modelEntityType = _allModelEntityTypes.SingleOrDefault(x => x.ClrType.Equals(modelType)); if (modelEntityType == null) { throw new InvalidOperationException(string.Format(ExceptionMessages.CannotCreateDbSetTypeNotIncludedInModel, invokedMethod.GetGenericArguments().Single().Name)); } var setUpModelMethod = typeof(NoSetUpHandler).GetMethods(BindingFlags.Instance | BindingFlags.NonPublic) .Single(x => x.Name.Equals(modelEntityType.FindPrimaryKey() != null ? "SetUpModel" : "SetUpReadOnlyModel")); setUpModelMethod.MakeGenericMethod(modelType).Invoke(this, new[] { mockedDbContext }); return RouteAction.Return(invokedMethod.Invoke(mockedDbContext, arguments?.ToArray())); } private Type GetModelType(MethodInfo invokedMethod) { var dbContextModelProperty = _dbContextModelProperties.SingleOrDefault(x => x.GetMethod.Name.Equals(invokedMethod.Name)); if (dbContextModelProperty != null) { return dbContextModelProperty.PropertyType.GetGenericArguments().Single(); } if (!invokedMethod.IsGenericMethod) { return null; } var dbContextMethod = typeof(DbContext).GetMethods(BindingFlags.Instance | BindingFlags.Public) .SingleOrDefault(x => x.IsGenericMethod && x.GetGenericMethodDefinition().Equals(invokedMethod.GetGenericMethodDefinition())); if (dbContextMethod != null) { return invokedMethod.GetGenericArguments().Single(); } return null; } private void SetUpModel(TDbContext mockedDbContext) where TEntity : class { var mockedDbSet = _dbContext.Set().CreateMockedDbSet(); var property = typeof(TDbContext).GetProperties().SingleOrDefault(p => p.PropertyType == typeof(DbSet)); if (property != null) { property.GetValue(mockedDbContext.Configure()).Returns(callInfo => mockedDbSet); } else { Logger.LogDebug("Could not find a DbContext property for type '{type}'", typeof(TEntity)); } mockedDbContext.Configure().Set().Returns(callInfo => mockedDbSet); mockedDbContext.Add(Arg.Any()).Returns(callInfo => _dbContext.Add(callInfo.Arg())); mockedDbContext.AddAsync(Arg.Any(), Arg.Any()) .Returns(callInfo => _dbContext.AddAsync(callInfo.Arg(), callInfo.Arg())); mockedDbContext.Attach(Arg.Any()).Returns(callInfo => _dbContext.Attach(callInfo.Arg())); mockedDbContext.Entry(Arg.Any()).Returns(callInfo => _dbContext.Entry(callInfo.Arg())); mockedDbContext.Find(Arg.Any()).Returns(callInfo => _dbContext.Find(callInfo.Arg())); mockedDbContext.FindAsync(Arg.Any()).Returns(callInfo => _dbContext.FindAsync(callInfo.Arg())); mockedDbContext.FindAsync(Arg.Any(), Arg.Any()) .Returns(callInfo => _dbContext.FindAsync(callInfo.Arg(), callInfo.Arg())); mockedDbContext.Remove(Arg.Any()).Returns(callInfo => _dbContext.Remove(callInfo.Arg())); mockedDbContext.Update(Arg.Any()).Returns(callInfo => _dbContext.Update(callInfo.Arg())); } private void SetUpReadOnlyModel(TDbContext mockedDbContext) where TEntity : class { var mockedReadOnlyDbSet = _dbContext.Set().CreateMockedReadOnlyDbSet(); var property = typeof(TDbContext).GetProperties().SingleOrDefault(p => p.PropertyType == typeof(DbSet)); if (property != null) { property.GetValue(mockedDbContext.Configure()).Returns(callInfo => mockedReadOnlyDbSet); } else { Logger.LogDebug("Could not find a DbContext property for type '{type}'", typeof(TEntity)); } mockedDbContext.Configure().Set().Returns(callInfo => mockedReadOnlyDbSet); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.NSubstitute.Tests/BaseForDbContextTests.cs ================================================ using System; using System.Collections.Generic; using EntityFrameworkCore.Testing.NSubstitute.Extensions; using Microsoft.EntityFrameworkCore; namespace EntityFrameworkCore.Testing.NSubstitute.Tests { public abstract class BaseForDbContextTests : Common.Tests.BaseForDbContextTests where T : DbContext { public override void AddExecuteSqlInterpolatedResult(T mockedDbContext, int expectedResult) { mockedDbContext.AddExecuteSqlInterpolatedResult(expectedResult); } public override void AddExecuteSqlInterpolatedResult(T mockedDbContext, FormattableString sql, int expectedResult) { mockedDbContext.AddExecuteSqlInterpolatedResult(sql, expectedResult); } public override void AddExecuteSqlInterpolatedResult(T mockedDbContext, string sql, IEnumerable parameters, int expectedResult) { mockedDbContext.AddExecuteSqlInterpolatedResult(sql, parameters, expectedResult); } public override void AddExecuteSqlRawResult(T mockedDbContext, int expectedResult) { mockedDbContext.AddExecuteSqlRawResult(expectedResult); } public override void AddExecuteSqlRawResult(T mockedDbContext, string sql, int expectedResult) { mockedDbContext.AddExecuteSqlRawResult(sql, expectedResult); } public override void AddExecuteSqlRawResult(T mockedDbContext, string sql, IEnumerable parameters, int expectedResult) { mockedDbContext.AddExecuteSqlRawResult(sql, parameters, expectedResult); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.NSubstitute.Tests/BaseForDbQueryTests.cs ================================================ using System; using System.Collections.Generic; using EntityFrameworkCore.Testing.Common.Tests; using EntityFrameworkCore.Testing.NSubstitute.Extensions; using Microsoft.EntityFrameworkCore; using NUnit.Framework; namespace EntityFrameworkCore.Testing.NSubstitute.Tests { public abstract class BaseForDbQueryTests : BaseForReadOnlyDbSetTests where T : BaseTestEntity { protected TestDbContext MockedDbContext; [SetUp] public override void SetUp() { base.SetUp(); MockedDbContext = Create.MockedDbContextFor(); } protected override void AddFromSqlRawResult(DbSet mockedDbSet, IEnumerable expectedResult) { mockedDbSet.AddFromSqlRawResult(expectedResult); } protected override void AddFromSqlRawResult(DbSet mockedDbSet, string sql, IEnumerable expectedResult) { mockedDbSet.AddFromSqlRawResult(sql, expectedResult); } protected override void AddFromSqlRawResult(DbSet mockedDbSet, string sql, IEnumerable parameters, IEnumerable expectedResult) { mockedDbSet.AddFromSqlRawResult(sql, parameters, expectedResult); } protected override void AddFromSqlInterpolatedResult(DbSet mockedDbSet, IEnumerable expectedResult) { mockedDbSet.AddFromSqlInterpolatedResult(expectedResult); } protected override void AddFromSqlInterpolatedResult(DbSet mockedDbSet, FormattableString sql, IEnumerable expectedResult) { mockedDbSet.AddFromSqlInterpolatedResult(sql, expectedResult); } protected override void AddFromSqlInterpolatedResult(DbSet mockedDbSet, string sql, IEnumerable parameters, IEnumerable expectedResult) { mockedDbSet.AddFromSqlInterpolatedResult(sql, parameters, expectedResult); } protected override void AddToReadOnlySource(DbSet mockedDbQuery, T item) { mockedDbQuery.AddToReadOnlySource(item); } protected override void AddRangeToReadOnlySource(DbSet mockedDbQuery, IEnumerable items) { mockedDbQuery.AddRangeToReadOnlySource(items); } protected override void ClearReadOnlySource(DbSet mockedDbQuery) { mockedDbQuery.ClearReadOnlySource(); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.NSubstitute.Tests/BaseForDbSetTests.cs ================================================ using System; using System.Collections.Generic; using EntityFrameworkCore.Testing.Common.Tests; using EntityFrameworkCore.Testing.NSubstitute.Extensions; using Microsoft.EntityFrameworkCore; namespace EntityFrameworkCore.Testing.NSubstitute.Tests { public abstract class BaseForDbSetTests : BaseForDbSetTests where T : BaseTestEntity { protected override TestDbContext CreateMockedDbContext() { return Create.MockedDbContextFor(); } protected override void AddFromSqlRawResult(DbSet mockedDbSet, IEnumerable expectedResult) { mockedDbSet.AddFromSqlRawResult(expectedResult); } protected override void AddFromSqlRawResult(DbSet mockedDbSet, string sql, IEnumerable expectedResult) { mockedDbSet.AddFromSqlRawResult(sql, expectedResult); } protected override void AddFromSqlRawResult(DbSet mockedDbSet, string sql, IEnumerable parameters, IEnumerable expectedResult) { mockedDbSet.AddFromSqlRawResult(sql, parameters, expectedResult); } protected override void AddFromSqlInterpolatedResult(DbSet mockedDbSet, IEnumerable expectedResult) { mockedDbSet.AddFromSqlInterpolatedResult(expectedResult); } protected override void AddFromSqlInterpolatedResult(DbSet mockedDbSet, FormattableString sql, IEnumerable expectedResult) { mockedDbSet.AddFromSqlInterpolatedResult(sql, expectedResult); } protected override void AddFromSqlInterpolatedResult(DbSet mockedDbSet, string sql, IEnumerable parameters, IEnumerable expectedResult) { mockedDbSet.AddFromSqlInterpolatedResult(sql, parameters, expectedResult); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.NSubstitute.Tests/ByPropertyDbSetTests.cs ================================================ using System.Linq; using EntityFrameworkCore.Testing.Common.Tests; namespace EntityFrameworkCore.Testing.NSubstitute.Tests { public class ByPropertyDbSetTests : BaseForDbSetTests { protected override IQueryable Queryable => MockedDbContext.TestEntities; } } ================================================ FILE: src/EntityFrameworkCore.Testing.NSubstitute.Tests/ByPropertyReadOnlyDbSetExceptionTests.cs ================================================ using EntityFrameworkCore.Testing.Common.Tests; using Microsoft.EntityFrameworkCore; using NUnit.Framework; namespace EntityFrameworkCore.Testing.NSubstitute.Tests { public class ByPropertyReadOnlyDbSetExceptionTests : ReadOnlyDbSetExceptionTests { protected TestDbContext MockedDbContext; protected override DbSet DbSet => MockedDbContext.TestReadOnlyEntities; [SetUp] public override void SetUp() { base.SetUp(); MockedDbContext = Create.MockedDbContextFor(); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.NSubstitute.Tests/ByPropertyReadOnlyDbSetTests.cs ================================================ using System.Linq; using EntityFrameworkCore.Testing.Common.Tests; namespace EntityFrameworkCore.Testing.NSubstitute.Tests { public class ByPropertyReadOnlyDbSetTests : BaseForDbQueryTests { protected override IQueryable Queryable => MockedDbContext.Set(); } } ================================================ FILE: src/EntityFrameworkCore.Testing.NSubstitute.Tests/ByTypeDbSetTests.cs ================================================ using System.Linq; using System.Linq.Expressions; using EntityFrameworkCore.Testing.Common.Tests; using NSubstitute; using NUnit.Framework; namespace EntityFrameworkCore.Testing.NSubstitute.Tests { public class ByTypeDbSetTests : BaseForDbSetTests { protected override IQueryable Queryable => MockedDbContext.Set(); [Test(Description = "This test ensures that method invoked via CallBase = true are verifiable")] public override void Select_ReturnsSequence() { base.Select_ReturnsSequence(); Queryable.Provider.Received(2).CreateQuery(Arg.Any()); Queryable.Provider.Received(2).CreateQuery(Arg.Is(mce => mce.Method.Name.Equals(nameof(System.Linq.Queryable.Select)))); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.NSubstitute.Tests/ByTypeReadOnlyDbSetExceptionTests.cs ================================================ using EntityFrameworkCore.Testing.Common.Tests; using Microsoft.EntityFrameworkCore; using NUnit.Framework; namespace EntityFrameworkCore.Testing.NSubstitute.Tests { public class ByTypeReadOnlyDbSetExceptionTests : ReadOnlyDbSetExceptionTests { protected TestDbContext MockedDbContext; protected override DbSet DbSet => MockedDbContext.Set(); [SetUp] public override void SetUp() { base.SetUp(); MockedDbContext = Create.MockedDbContextFor(); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.NSubstitute.Tests/ByTypeReadOnlyDbSetTests.cs ================================================ using System.Linq; using EntityFrameworkCore.Testing.Common.Tests; namespace EntityFrameworkCore.Testing.NSubstitute.Tests { public class ByTypeReadOnlyDbSetTests : BaseForDbQueryTests { protected override IQueryable Queryable => MockedDbContext.Set(); } } ================================================ FILE: src/EntityFrameworkCore.Testing.NSubstitute.Tests/CreateFactoryTests.cs ================================================ using System; using System.Linq; using Castle.DynamicProxy; using EntityFrameworkCore.Testing.Common.Tests; using Microsoft.EntityFrameworkCore; using NUnit.Framework; namespace EntityFrameworkCore.Testing.NSubstitute.Tests { public class CreateFactoryTests : BaseForTests { [Test] public void CreateMockedDbContextFor_Type_CreatesMockedDbContext() { var mocked = Create.MockedDbContextFor(); Assert.Multiple(() => { Assert.That(mocked, Is.Not.Null); Assert.That(ProxyUtil.IsProxy(mocked), Is.True); }); } [Test] public void CreateMockedQueryProviderFor_Queryable_CreatesMockedQueryProvider() { var dbContextToMock = new TestDbContext(new DbContextOptionsBuilder().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options); var mocked = Create.MockedQueryProviderFor(dbContextToMock.TestEntities); Assert.Multiple(() => { Assert.That(mocked, Is.Not.Null); Assert.That(ProxyUtil.IsProxy(mocked), Is.True); }); } [Test] public void CreateMockedQueryProviderFor_NullQueryable_ThrowsException() { Assert.Throws(() => { var mocked = Create.MockedQueryProviderFor((IQueryable) null); }); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.NSubstitute.Tests/DbContextTestsUsingConstructorParameters.cs ================================================ using System; using EntityFrameworkCore.Testing.Common.Tests; using Microsoft.EntityFrameworkCore; using NUnit.Framework; namespace EntityFrameworkCore.Testing.NSubstitute.Tests { public class DbContextTestsUsingConstructorParameters : BaseForDbContextTests { [SetUp] public override void SetUp() { base.SetUp(); MockedDbContext = Create.MockedDbContextFor(new DbContextOptionsBuilder().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.NSubstitute.Tests/DbContextTestsUsingType.cs ================================================ using EntityFrameworkCore.Testing.Common.Tests; using NUnit.Framework; namespace EntityFrameworkCore.Testing.NSubstitute.Tests { public class DbContextTestsUsingType : BaseForDbContextTests { [SetUp] public override void SetUp() { base.SetUp(); MockedDbContext = Create.MockedDbContextFor(); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.NSubstitute.Tests/EntityFrameworkCore.Testing.NSubstitute.Tests.csproj ================================================ net10.0 false NU1605 true NU1605 runtime; build; native; contentfiles; analyzers; buildtransitive all all runtime; build; native; contentfiles; analyzers; buildtransitive ================================================ FILE: src/EntityFrameworkCore.Testing.NSubstitute.Tests/Issue114Tests.cs ================================================ namespace EntityFrameworkCore.Testing.NSubstitute.Tests { public class Issue114Tests : Common.Tests.Issue114Tests { protected override TestDbContext MockedDbContextFactory() { return Create.MockedDbContextFor(); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.NSubstitute.Tests/Issue117Tests.cs ================================================ namespace EntityFrameworkCore.Testing.NSubstitute.Tests { public class Issue117Tests : Common.Tests.Issue117Tests { protected override TestDbContext MockedDbContextFactory() { return Create.MockedDbContextFor(); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.NSubstitute.Tests/Issue126Tests.cs ================================================ using System; using EntityFrameworkCore.Testing.Common.Tests; using Microsoft.EntityFrameworkCore; using NUnit.Framework; namespace EntityFrameworkCore.Testing.NSubstitute.Tests { public class Issue126Tests : Issue126Tests { [SetUp] public override void SetUp() { base.SetUp(); var options = new DbContextOptionsBuilder() .UseInMemoryDatabase(Guid.NewGuid().ToString()) .Options; DbContextFactory = () => Create.MockedDbContextFor(options); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.NSubstitute.Tests/Issue1Tests.cs ================================================ using System; using System.Data; using Microsoft.Data.SqlClient; using System.Linq; using System.Threading.Tasks; using AutoFixture; using Castle.DynamicProxy; using EntityFrameworkCore.Testing.Common.Tests; using EntityFrameworkCore.Testing.NSubstitute.Extensions; using Microsoft.EntityFrameworkCore; using NUnit.Framework; namespace EntityFrameworkCore.Testing.NSubstitute.Tests { public class Issue1Tests : BaseForTests { [Test] public void CreateMockedDbContextFor_ParametersForSpecificConstructor_CreatesSubstitute() { var mockedDbContext = Create.MockedDbContextFor(new DbContextOptionsBuilder().UseInMemoryDatabase(Guid.NewGuid().ToString()) .EnableSensitiveDataLogging() .Options); Assert.Multiple(() => { Assert.That(mockedDbContext, Is.Not.Null); Assert.That(ProxyUtil.IsProxy(mockedDbContext), Is.True); }); } [Test] public async Task ExecuteSqlRawAsync_SpecifiedSqlAndSqlParameter_ReturnsExpectedResultAndSetsOutputParameterValue() { var expectedResult = Fixture.Create(); var mockedDbContext = Create.MockedDbContextFor(); mockedDbContext.AddExecuteSqlRawResult(-1, (sql, parameters) => { ((SqlParameter) parameters.ElementAt(0)).Value = expectedResult; }); var outputParameter = new SqlParameter("OutputParameter", SqlDbType.NVarChar, 255) { Direction = ParameterDirection.Output }; var result = await mockedDbContext.Database.ExecuteSqlRawAsync(@"EXEC [StoredProcedureWithOutputParameter] @OutputParameter = @Result OUTPUT", outputParameter); Assert.Multiple(() => { Assert.That(result, Is.EqualTo(-1)); Assert.That(outputParameter.Value.ToString(), Is.EqualTo(expectedResult)); }); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.NSubstitute.Tests/Issue49Tests.cs ================================================ using EntityFrameworkCore.Testing.Common.Tests; using NUnit.Framework; namespace EntityFrameworkCore.Testing.NSubstitute.Tests { public class Issue49Tests : Issue49Tests { [SetUp] public override void SetUp() { base.SetUp(); DbContext = Create.MockedDbContextFor(); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.NSubstitute.Tests/Issue4Tests.cs ================================================ using System; using System.Linq; using System.Threading.Tasks; using AutoFixture; using EntityFrameworkCore.Testing.Common.Tests; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Query; using NUnit.Framework; namespace EntityFrameworkCore.Testing.NSubstitute.Tests { public class Issue4Tests : BaseForTests { [Test] public void AsQueryable_Set_ReturnsIQueryableOfTWithMockedQueryProvider() { var mockedDbContext = Create.MockedDbContextFor(); var mockedSetAsQueryable = mockedDbContext.TestEntities.AsQueryable(); var asyncProvider = mockedSetAsQueryable.Provider as IAsyncQueryProvider; Assert.That(asyncProvider, Is.Not.Null); } [Test] public async Task AsQueryableThenWhereThenSingleOrDefaultAsync_WhereOperationReturnsFalse_ReturnsDefault() { var entities = Fixture.CreateMany().ToList(); var mockedDbContext = Create.MockedDbContextFor(); var mockedSet = mockedDbContext.TestEntities; mockedSet.AddRange(entities); mockedDbContext.SaveChanges(); var result = await mockedSet.AsQueryable().Where(x => x.Id.Equals(Guid.NewGuid())).SingleOrDefaultAsync(); Assert.That(result, Is.Null); } [Test] public async Task AsQueryableThenWhereThenSingleOrDefaultAsync_WhereOperationReturnsTrue_ReturnsSingleEntity() { var entities = Fixture.CreateMany().ToList(); var entityToFind = entities.ElementAt(1); var mockedDbContext = Create.MockedDbContextFor(); var mockedSet = mockedDbContext.TestEntities; mockedSet.AddRange(entities); mockedDbContext.SaveChanges(); var result = await mockedSet.AsQueryable().Where(x => x.Id.Equals(entityToFind.Id)).SingleOrDefaultAsync(); Assert.That(result, Is.EqualTo(entityToFind)); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.NSubstitute.Tests/Issue6Tests.cs ================================================ using System; using System.Collections.Generic; using AutoFixture; using EntityFrameworkCore.Testing.Common.Tests; using EntityFrameworkCore.Testing.NSubstitute.Extensions; using Microsoft.EntityFrameworkCore; using NUnit.Framework; namespace EntityFrameworkCore.Testing.NSubstitute.Tests { public class Issue6Tests : BaseForTests { private static IEnumerable FromSqlInterpolated_SpecifiedSqlWithNullParameters_TestCases { get { yield return new TestCaseData(null, null); yield return new TestCaseData(null, 1); yield return new TestCaseData(DateTime.Parse("21 May 2020 9:05 PM"), null); } } [TestCaseSource(nameof(FromSqlInterpolated_SpecifiedSqlWithNullParameters_TestCases))] public void FromSqlInterpolated_SpecifiedSqlWithNullParameters_ReturnsExpectedResult(DateTime? dateTimeValue, int? intValue) { var expectedResult = new List { Fixture.Create() }; var mockedDbContext = Create.MockedDbContextFor(); mockedDbContext.Set().AddFromSqlInterpolatedResult($"SELECT * FROM [SqlFunctionWithNullableParameters]({dateTimeValue}, {intValue})", expectedResult); var actualResult = mockedDbContext.Set().FromSqlInterpolated($"SELECT * FROM [SqlFunctionWithNullableParameters]({dateTimeValue}, {intValue})"); Assert.That(actualResult, Is.EqualTo(expectedResult)); } [Test] public void FromSqlInterpolated_SpecifiedSqlWithDbNullParameters_ReturnsExpectedResult() { var expectedResult = new List { Fixture.Create() }; var mockedDbContext = Create.MockedDbContextFor(); mockedDbContext.Set().AddFromSqlInterpolatedResult($"SELECT * FROM [SqlFunctionWithNullableParameters]({DBNull.Value}, {DBNull.Value})", expectedResult); var actualResult = mockedDbContext.Set().FromSqlInterpolated($"SELECT * FROM [SqlFunctionWithNullableParameters]({DBNull.Value}, {DBNull.Value})"); Assert.That(actualResult, Is.EqualTo(expectedResult)); } } } ================================================ FILE: src/EntityFrameworkCore.Testing.NSubstitute.Tests/Issue88Tests.cs ================================================ using System; using EntityFrameworkCore.Testing.Common.Tests; using Microsoft.EntityFrameworkCore; using NUnit.Framework; namespace EntityFrameworkCore.Testing.NSubstitute.Tests { public class Issue88Tests : Issue88Tests { [SetUp] public override void SetUp() { base.SetUp(); var options = new DbContextOptionsBuilder() .UseInMemoryDatabase(Guid.NewGuid().ToString()) .Options; DbContextFactory = () => Create.MockedDbContextFor(options); } } }