├── .gitignore ├── Changelog.txt ├── LICENSE ├── README.md ├── azure-pipelines.yml └── src ├── Moq.EntityFrameworkCore.Examples ├── Moq.EntityFrameworkCore.Examples.csproj ├── Users │ ├── Entities │ │ ├── Role.cs │ │ └── User.cs │ ├── UsersContext.cs │ └── UsersService.cs └── UsersServiceTest.cs ├── Moq.EntityFrameworkCore.Tests ├── DbAsyncQueryProvider │ ├── InMemoryAsyncEnumerableTests.cs │ ├── InMemoryAsyncQueryProviderTests.cs │ └── InMemoryDbAsyncEnumeratorTests.cs └── Moq.EntityFrameworkCore.Tests.csproj ├── Moq.EntityFrameworkCore.sln └── Moq.EntityFrameworkCore ├── DbAsyncQueryProvider ├── InMemoryAsyncEnumerable.cs ├── InMemoryAsyncQueryProvider.cs └── InMemoryDbAsyncEnumerator.cs ├── Dynamic ├── GlobalFilterDbSetExtensionsDynamic.cs └── MoqExtensionsDynamic.cs ├── GlobalFilterDbSetExtensions.cs ├── Moq.EntityFrameworkCore.csproj └── MoqExtensions.cs /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/visualstudio 3 | 4 | ### VisualStudio ### 5 | ## Ignore Visual Studio temporary files, build results, and 6 | ## files generated by popular Visual Studio add-ons. 7 | 8 | # User-specific files 9 | *.suo 10 | *.user 11 | *.userosscache 12 | *.sln.docstates 13 | 14 | # User-specific files (MonoDevelop/Xamarin Studio) 15 | *.userprefs 16 | 17 | # Build results 18 | [Dd]ebug/ 19 | [Dd]ebugPublic/ 20 | [Rr]elease/ 21 | [Rr]eleases/ 22 | x64/ 23 | x86/ 24 | bld/ 25 | [Bb]in/ 26 | [Oo]bj/ 27 | [Ll]og/ 28 | 29 | # Visual Studio 2015 cache/options directory 30 | .vs/ 31 | # Uncomment if you have tasks that create the project's static files in wwwroot 32 | #wwwroot/ 33 | 34 | # MSTest test Results 35 | [Tt]est[Rr]esult*/ 36 | [Bb]uild[Ll]og.* 37 | 38 | # NUNIT 39 | *.VisualState.xml 40 | TestResult.xml 41 | 42 | # Build Results of an ATL Project 43 | [Dd]ebugPS/ 44 | [Rr]eleasePS/ 45 | dlldata.c 46 | 47 | # DNX 48 | project.lock.json 49 | project.fragment.lock.json 50 | artifacts/ 51 | 52 | *_i.c 53 | *_p.c 54 | *_i.h 55 | *.ilk 56 | *.meta 57 | *.obj 58 | *.pch 59 | *.pdb 60 | *.pgc 61 | *.pgd 62 | *.rsp 63 | *.sbr 64 | *.tlb 65 | *.tli 66 | *.tlh 67 | *.tmp 68 | *.tmp_proj 69 | *.log 70 | *.vspscc 71 | *.vssscc 72 | .builds 73 | *.pidb 74 | *.svclog 75 | *.scc 76 | 77 | # Chutzpah Test files 78 | _Chutzpah* 79 | 80 | # Visual C++ cache files 81 | ipch/ 82 | *.aps 83 | *.ncb 84 | *.opendb 85 | *.opensdf 86 | *.sdf 87 | *.cachefile 88 | *.VC.db 89 | *.VC.VC.opendb 90 | 91 | # Visual Studio profiler 92 | *.psess 93 | *.vsp 94 | *.vspx 95 | *.sap 96 | 97 | # TFS 2012 Local Workspace 98 | $tf/ 99 | 100 | # Guidance Automation Toolkit 101 | *.gpState 102 | 103 | # ReSharper is a .NET coding add-in 104 | _ReSharper*/ 105 | *.[Rr]e[Ss]harper 106 | *.DotSettings.user 107 | 108 | # JustCode is a .NET coding add-in 109 | .JustCode 110 | 111 | # TeamCity is a build add-in 112 | _TeamCity* 113 | 114 | # DotCover is a Code Coverage Tool 115 | *.dotCover 116 | 117 | # Visual Studio code coverage results 118 | *.coverage 119 | *.coveragexml 120 | 121 | # NCrunch 122 | _NCrunch_* 123 | .*crunch*.local.xml 124 | nCrunchTemp_* 125 | 126 | # MightyMoose 127 | *.mm.* 128 | AutoTest.Net/ 129 | 130 | # Web workbench (sass) 131 | .sass-cache/ 132 | 133 | # Installshield output folder 134 | [Ee]xpress/ 135 | 136 | # DocProject is a documentation generator add-in 137 | DocProject/buildhelp/ 138 | DocProject/Help/*.HxT 139 | DocProject/Help/*.HxC 140 | DocProject/Help/*.hhc 141 | DocProject/Help/*.hhk 142 | DocProject/Help/*.hhp 143 | DocProject/Help/Html2 144 | DocProject/Help/html 145 | 146 | # Click-Once directory 147 | publish/ 148 | 149 | # Publish Web Output 150 | *.[Pp]ublish.xml 151 | *.azurePubxml 152 | # Comment the next line if you want to checkin your web deploy settings 153 | # but database connection strings (with potential passwords) will be unencrypted 154 | *.pubxml 155 | *.publishproj 156 | 157 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 158 | # checkin your Azure Web App publish settings, but sensitive information contained 159 | # in these scripts will be unencrypted 160 | PublishScripts/ 161 | 162 | # NuGet Packages 163 | *.nupkg 164 | # The packages folder can be ignored because of Package Restore 165 | **/packages/* 166 | # except build/, which is used as an MSBuild target. 167 | !**/packages/build/ 168 | # Uncomment if necessary however generally it will be regenerated when needed 169 | #!**/packages/repositories.config 170 | # NuGet v3's project.json files produces more ignoreable files 171 | *.nuget.props 172 | *.nuget.targets 173 | 174 | # Microsoft Azure Build Output 175 | csx/ 176 | *.build.csdef 177 | 178 | # Microsoft Azure Emulator 179 | ecf/ 180 | rcf/ 181 | 182 | # Windows Store app package directories and files 183 | AppPackages/ 184 | BundleArtifacts/ 185 | Package.StoreAssociation.xml 186 | _pkginfo.txt 187 | 188 | # Visual Studio cache files 189 | # files ending in .cache can be ignored 190 | *.[Cc]ache 191 | # but keep track of directories ending in .cache 192 | !*.[Cc]ache/ 193 | 194 | # Others 195 | ClientBin/ 196 | ~$* 197 | *~ 198 | *.dbmdl 199 | *.dbproj.schemaview 200 | *.jfm 201 | *.pfx 202 | *.publishsettings 203 | node_modules/ 204 | orleans.codegen.cs 205 | 206 | # Since there are multiple workflows, uncomment next line to ignore bower_components 207 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 208 | #bower_components/ 209 | 210 | # RIA/Silverlight projects 211 | Generated_Code/ 212 | 213 | # Backup & report files from converting an old project file 214 | # to a newer Visual Studio version. Backup files are not needed, 215 | # because we have git ;-) 216 | _UpgradeReport_Files/ 217 | Backup*/ 218 | UpgradeLog*.XML 219 | UpgradeLog*.htm 220 | 221 | # SQL Server files 222 | *.mdf 223 | *.ldf 224 | 225 | # Business Intelligence projects 226 | *.rdl.data 227 | *.bim.layout 228 | *.bim_*.settings 229 | 230 | # Microsoft Fakes 231 | FakesAssemblies/ 232 | 233 | # GhostDoc plugin setting file 234 | *.GhostDoc.xml 235 | 236 | # Node.js Tools for Visual Studio 237 | .ntvs_analysis.dat 238 | 239 | # Visual Studio 6 build log 240 | *.plg 241 | 242 | # Visual Studio 6 workspace options file 243 | *.opt 244 | 245 | # Visual Studio LightSwitch build output 246 | **/*.HTMLClient/GeneratedArtifacts 247 | **/*.DesktopClient/GeneratedArtifacts 248 | **/*.DesktopClient/ModelManifest.xml 249 | **/*.Server/GeneratedArtifacts 250 | **/*.Server/ModelManifest.xml 251 | _Pvt_Extensions 252 | 253 | # Paket dependency manager 254 | .paket/paket.exe 255 | paket-files/ 256 | 257 | # FAKE - F# Make 258 | .fake/ 259 | 260 | # JetBrains Rider 261 | .idea/ 262 | *.sln.iml 263 | 264 | # CodeRush 265 | .cr/ 266 | 267 | # Python Tools for Visual Studio (PTVS) 268 | __pycache__/ 269 | *.pyc 270 | 271 | # Cake - Uncomment if you are using it 272 | # tools/ 273 | 274 | ### VisualStudio Patch ### 275 | build/ -------------------------------------------------------------------------------- /Changelog.txt: -------------------------------------------------------------------------------- 1 | Version 1.0.0: 2 | Initial release 3 | 4 | Version 2.0.0: 5 | Update nuget packages version 6 | 7 | Version 2.0.1: 8 | Change extension method name to ReturnDbSet 9 | 10 | Version 3.0.0.4 11 | Added support for EF3.0 12 | 13 | Version 3.1.2.6 14 | Added support for interfaces and classes that are not delivering from DbContext 15 | 16 | Version 3.1.2.13 17 | Added support for SetupSequentialResult 18 | 19 | Version 5.0.0.1 20 | Added support for EntityFrameworkCore 5.0.0 21 | 22 | Version 6.0.0.1 23 | Added support for EntityFrameworkCore 6.0.0 24 | 25 | Version 6.0.1.3 26 | Added support for SetupGet 27 | 28 | Version 6.0.1.4 29 | Package versions update 30 | 31 | Version 7.0.0.1 32 | Added support for EntityFrameworkCore 7.0.0 33 | 34 | Version 8.0.0.1 35 | Added support for EntityFrameworkCore 8.0.0 36 | 37 | Version 8.0.1.1 38 | Updated EntityFrameworkCore 8.0.1 39 | 40 | Version 9.0.0.1 41 | Updated EntityFrameworkCore 9.0.0 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Michał Jankowski 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Moq.EntityFrameworkCore 2 | [![Build Status](https://dev.azure.com/OpenSource-jankowskimichalpl/Moq.EntityFrameworkCore/_apis/build/status/MichalJankowskii.Moq.EntityFrameworkCore?branchName=master)](https://dev.azure.com/OpenSource-jankowskimichalpl/Moq.EntityFrameworkCore/_build/latest?definitionId=1&branchName=master) 3 | [![Downloads](https://img.shields.io/nuget/dt/Moq.EntityFrameworkCore.svg)](https://www.nuget.org/packages/Moq.EntityFrameworkCore/) 4 | 5 | This library helps you mocking EntityFramework contexts. Now you will be able to test methods that are using `DbSet` or `DbQuery` from `DbContext` in an effective way. 6 | ## Installation - NuGet Packages 7 | ``` 8 | Install-Package Moq.EntityFrameworkCore 9 | ``` 10 | 11 | ## Usage 12 | For example we can assume that we have the following production code: 13 | ``` 14 | public class UsersContext : DbContext 15 | { 16 | public virtual DbSet Users { get; set; } 17 | } 18 | ``` 19 | 20 | To mock Users and Roles you only need to implement the following 3 steps: 21 | 22 | 1\. Create `DbContext` mock: 23 | ```csharp 24 | var userContextMock = new Mock(); 25 | ``` 26 | 2\. Generate your entities: 27 | ```csharp 28 | IList users = ...; 29 | ``` 30 | 3\. Setup `DbSet` or `DbQuery` property: 31 | ```csharp 32 | userContextMock.Setup(x => x.Users).ReturnsDbSet(users); 33 | ``` 34 | or 35 | ```csharp 36 | userContextMock.SetupGet(x => x.Users).ReturnsDbSet(users); 37 | ``` 38 | or 39 | ```csharp 40 | userContextMock.SetupSequence(x => x.Set()) 41 | .ReturnsDbSet(new List()) 42 | .ReturnsDbSet(users); 43 | ``` 44 | 45 | 46 | 47 | And this is all. You can use your `DbContext` in your tests. 48 | 49 | The second option is mocking `DbSet` that is part of the interface: 50 | ```csharp 51 | public interface IBlogContext 52 | { 53 | DbSet Posts { get; } 54 | } 55 | ``` 56 | 57 | And then use: 58 | ```csharp 59 | var posts = new List(); 60 | var contextMock = new Mock(); 61 | contextMock.Setup(p => p.Posts).ReturnsDbSet(posts); 62 | ``` 63 | 64 | ## Using ReturnsDbSetWithGlobalFilter 65 | You can also use `ReturnsDbSetWithGlobalFilter` to set up a `DbSet` with a global filter. For example: 66 | ```csharp 67 | var users = new List { new User { IsActive = true }, new User { IsActive = false } }; 68 | var userContextMock = new Mock(); 69 | userContextMock.Setup(x => x.Users).ReturnsDbSetWithGlobalFilter(users, u => u.IsActive); 70 | ``` 71 | 72 | ## New Usage Option: ReturnsDbSetDynamic 73 | You can now use the ReturnsDbSetDynamic method for scenarios where you need lazy evaluation of your DbSet. This ensures that the DbSet is re-evaluated dynamically at runtime. 74 | 75 | ```csharp 76 | userContextMock.Setup(x => x.Users).ReturnsDbSetDynamic(users); 77 | ``` 78 | 79 | ### Explanation of Differences 80 | - `ReturnsDbSet`: Statically resolves the DbSet value during setup. 81 | - `ReturnsDbSetDynamic`: Dynamically resolves the DbSet value using a lambda, ensuring it reflects changes at runtime. 82 | 83 | You will find examples of this library in the [repository](https://github.com/MichalJankowskii/Moq.EntityFrameworkCore/blob/master/src/Moq.EntityFrameworkCore.Examples/UsersServiceTest.cs). 84 | -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | trigger: 2 | branches: 3 | include: 4 | - master 5 | paths: 6 | include: 7 | - src/* 8 | 9 | pool: 10 | vmImage: 'ubuntu-latest' 11 | 12 | variables: 13 | buildConfiguration: 'Release' 14 | efVersion: '9.0.0' 15 | versionBuildNumber: $[counter('9.0.0', 1)] 16 | packageVersion: $(efVersion).$(versionBuildNumber) 17 | 18 | steps: 19 | - bash: echo $(packageVersion) 20 | displayName: Print version 21 | - task: UseDotNet@2 22 | displayName: 'Use .NET Core sdk' 23 | inputs: 24 | packageType: sdk 25 | version: 8.0.100 26 | installationPath: $(Agent.ToolsDirectory)/dotnet 27 | - task: DotNetCoreCLI@2 28 | displayName: 'Building' 29 | inputs: 30 | command: 'build' 31 | projects: 'src/Moq.EntityFrameworkCore.sln' 32 | arguments: '--configuration $(buildConfiguration)' 33 | - task: DotNetCoreCLI@2 34 | displayName: 'Testing' 35 | inputs: 36 | command: 'test' 37 | projects: 'src/Moq.EntityFrameworkCore.sln' 38 | arguments: '--configuration $(buildConfiguration)' 39 | publishTestResults: false 40 | testRunTitle: 'Testing' 41 | - task: DotNetCoreCLI@2 42 | displayName: "Packing" 43 | inputs: 44 | command: 'pack' 45 | packagesToPack: 'src/Moq.EntityFrameworkCore/Moq.EntityFrameworkCore.csproj' 46 | versioningScheme: byEnvVar 47 | versionEnvVar: packageVersion 48 | - task: PublishBuildArtifacts@1 49 | displayName: 'Publishing' 50 | inputs: 51 | PathtoPublish: '$(Build.ArtifactStagingDirectory)' 52 | ArtifactName: 'package' 53 | publishLocation: 'Container' 54 | -------------------------------------------------------------------------------- /src/Moq.EntityFrameworkCore.Examples/Moq.EntityFrameworkCore.Examples.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | all 16 | runtime; build; native; contentfiles; analyzers 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/Moq.EntityFrameworkCore.Examples/Users/Entities/Role.cs: -------------------------------------------------------------------------------- 1 | namespace Moq.EntityFrameworkCore.Examples.Users.Entities 2 | { 3 | public class Role 4 | { 5 | public int Id { get; set; } 6 | 7 | public string Name { get; set; } 8 | 9 | public bool IsEnabled { get; set; } 10 | } 11 | } -------------------------------------------------------------------------------- /src/Moq.EntityFrameworkCore.Examples/Users/Entities/User.cs: -------------------------------------------------------------------------------- 1 | namespace Moq.EntityFrameworkCore.Examples.Users.Entities 2 | { 3 | using System.Collections.Generic; 4 | 5 | public class User 6 | { 7 | public int Id { get; set; } 8 | public string Login { get; set; } 9 | 10 | public string Name { get; set; } 11 | 12 | public string Surname { get; set; } 13 | 14 | public bool AccountLocked { get; set; } 15 | 16 | public virtual List Roles { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Moq.EntityFrameworkCore.Examples/Users/UsersContext.cs: -------------------------------------------------------------------------------- 1 | namespace Moq.EntityFrameworkCore.Examples.Users 2 | { 3 | using Microsoft.EntityFrameworkCore; 4 | using Moq.EntityFrameworkCore.Examples.Users.Entities; 5 | 6 | public class UsersContext : DbContext 7 | { 8 | public virtual DbSet Users { get; set; } 9 | 10 | public virtual DbSet Roles { get; set; } 11 | } 12 | } -------------------------------------------------------------------------------- /src/Moq.EntityFrameworkCore.Examples/Users/UsersService.cs: -------------------------------------------------------------------------------- 1 | namespace Moq.EntityFrameworkCore.Examples.Users 2 | { 3 | using Microsoft.EntityFrameworkCore; 4 | using Moq.EntityFrameworkCore.Examples.Users.Entities; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Linq.Expressions; 9 | using System.Threading; 10 | using System.Threading.Tasks; 11 | 12 | public class UsersService 13 | { 14 | private readonly UsersContext usersContext; 15 | 16 | public UsersService(UsersContext usersContext) 17 | { 18 | this.usersContext = usersContext; 19 | } 20 | 21 | public async Task AddUser(User user) 22 | { 23 | await this.usersContext.Users.AddAsync(user); 24 | await this.usersContext.SaveChangesAsync(); 25 | } 26 | 27 | public IList GetLockedUsers() 28 | { 29 | return this.usersContext.Users.Where(x => x.AccountLocked).ToList(); 30 | } 31 | 32 | public async Task> GetLockedUsersAsync() 33 | { 34 | return await this.usersContext.Users.Where(x => x.AccountLocked).ToListAsync(); 35 | } 36 | 37 | public IList GetDisabledRoles() 38 | { 39 | return this.usersContext.Roles.Where(x => !x.IsEnabled).ToList(); 40 | } 41 | 42 | public async Task> GetDisabledRolesAsync() 43 | { 44 | return await this.usersContext.Roles.Where(x => !x.IsEnabled).ToListAsync(); 45 | } 46 | 47 | public async Task FindOneUserAsync(Expression> predicate) 48 | { 49 | return await this.usersContext.Set().FirstOrDefaultAsync(predicate); 50 | } 51 | 52 | public async Task> GetAllUsersAsync(CancellationToken cancellationToken) 53 | { 54 | return await this.usersContext.Users.ToListAsync(cancellationToken); 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /src/Moq.EntityFrameworkCore.Examples/UsersServiceTest.cs: -------------------------------------------------------------------------------- 1 | namespace Moq.EntityFrameworkCore.Examples 2 | { 3 | using AutoFixture; 4 | using Moq.EntityFrameworkCore; 5 | using Moq.EntityFrameworkCore.Examples.Users; 6 | using Moq.EntityFrameworkCore.Examples.Users.Entities; 7 | using System.Collections.Generic; 8 | using System.Threading.Tasks; 9 | using Xunit; 10 | using System.Linq; 11 | using System.Threading; 12 | using Microsoft.EntityFrameworkCore; 13 | using Moq.EntityFrameworkCore.Dynamic; 14 | 15 | public class UsersServiceTest 16 | { 17 | private static readonly Fixture Fixture = new Fixture(); 18 | 19 | [Fact] 20 | public void Given_ListOfUsersWithOneUserAccountLock_When_CheckingWhoIsLocked_Then_CorrectLockedUserIsReturned() 21 | { 22 | // Arrange 23 | IList users = GenerateNotLockedUsers(); 24 | var lockedUser = Fixture.Build().With(u => u.AccountLocked, true).Create(); 25 | users.Add(lockedUser); 26 | 27 | var userContextMock = new Mock(); 28 | userContextMock.Setup(x => x.Users).ReturnsDbSet(users); 29 | 30 | var usersService = new UsersService(userContextMock.Object); 31 | 32 | // Act 33 | var lockedUsers = usersService.GetLockedUsers(); 34 | 35 | // Assert 36 | Assert.Equal(new List { lockedUser }, lockedUsers); 37 | } 38 | 39 | [Fact] 40 | public void Given_ListOfUsersWithOneUserAccountLockAndMockingWithSetupGet_When_CheckingWhoIsLocked_Then_CorrectLockedUserIsReturned() 41 | { 42 | // Arrange 43 | IList users = GenerateNotLockedUsers(); 44 | var lockedUser = Fixture.Build().With(u => u.AccountLocked, true).Create(); 45 | users.Add(lockedUser); 46 | 47 | var userContextMock = new Mock(); 48 | userContextMock.SetupGet(x => x.Users).ReturnsDbSet(users); 49 | 50 | var usersService = new UsersService(userContextMock.Object); 51 | 52 | // Act 53 | var lockedUsers = usersService.GetLockedUsers(); 54 | 55 | // Assert 56 | Assert.Equal(new List { lockedUser }, lockedUsers); 57 | } 58 | 59 | [Fact] 60 | public async Task Given_ListOfUsersWithOneUserAccountLock_When_CheckingWhoIsLockedAsync_Then_CorrectLockedUserIsReturned() 61 | { 62 | // Arrange 63 | IList users = GenerateNotLockedUsers(); 64 | var lockedUser = Fixture.Build().With(u => u.AccountLocked, true).Create(); 65 | users.Add(lockedUser); 66 | 67 | var userContextMock = new Mock(); 68 | userContextMock.Setup(x => x.Users).ReturnsDbSet(users); 69 | 70 | var usersService = new UsersService(userContextMock.Object); 71 | 72 | // Act 73 | var lockedUsers = await usersService.GetLockedUsersAsync(); 74 | 75 | // Assert 76 | Assert.Equal(new List { lockedUser }, lockedUsers); 77 | } 78 | 79 | [Fact] 80 | public void Given_ListOfGroupsWithOneGroupDisabled_When_CheckingWhichOneIsDisabled_Then_CorrectDisabledRoleIsReturned() 81 | { 82 | // Arrange 83 | IList roles = GenerateEnabledGroups(); 84 | var disabledRole = Fixture.Build().With(u => u.IsEnabled, false).Create(); 85 | roles.Add(disabledRole); 86 | 87 | var userContextMock = new Mock(); 88 | userContextMock.Setup(x => x.Roles).ReturnsDbSet(roles); 89 | 90 | var usersService = new UsersService(userContextMock.Object); 91 | 92 | // Act 93 | var disabledRoles = usersService.GetDisabledRoles(); 94 | 95 | // Assert 96 | Assert.Equal(new List { disabledRole }, disabledRoles); 97 | } 98 | 99 | [Fact] 100 | public async Task Given_ListOfGroupsWithOneGroupDisabled_When_CheckingWhichOneIsDisabledAsync_Then_CorrectDisabledRoleIsReturned() 101 | { 102 | // Arrange 103 | IList roles = GenerateEnabledGroups(); 104 | var disabledRole = Fixture.Build().With(u => u.IsEnabled, false).Create(); 105 | roles.Add(disabledRole); 106 | 107 | var userContextMock = new Mock(); 108 | userContextMock.Setup(x => x.Roles).ReturnsDbSet(roles); 109 | 110 | var usersService = new UsersService(userContextMock.Object); 111 | 112 | // Act 113 | var disabledRoles = await usersService.GetDisabledRolesAsync(); 114 | 115 | // Assert 116 | Assert.Equal(new List { disabledRole }, disabledRoles); 117 | } 118 | 119 | [Fact] 120 | public async Task Given_ListOfUser_When_FindOneUserAsync_Then_CorrectUserIsReturned() 121 | { 122 | var users = GenerateNotLockedUsers(); 123 | var userContextMock = new Mock(); 124 | userContextMock.Setup(x => x.Set()).ReturnsDbSet(users); 125 | 126 | var usersService = new UsersService(userContextMock.Object); 127 | var user = users.FirstOrDefault(); 128 | 129 | //Act 130 | var userToAssert = await usersService.FindOneUserAsync(x => x.Id == user.Id); 131 | 132 | //Assert 133 | Assert.Equal(userToAssert, user); 134 | } 135 | 136 | [Fact] 137 | public async Task Given_Two_ListOfUser_Then_CorrectListIsReturned_InSequence() 138 | { 139 | var users = GenerateNotLockedUsers(); 140 | var userContextMock = new Mock(); 141 | userContextMock.SetupSequence(x => x.Set()) 142 | .ReturnsDbSet(new List()) 143 | .ReturnsDbSet(users); 144 | 145 | var usersService = new UsersService(userContextMock.Object); 146 | 147 | var user = users.FirstOrDefault(); 148 | 149 | //Act 150 | var userToAssertWhenFirstCall = await usersService.FindOneUserAsync(x => x.Id == user.Id); 151 | var userToAssertWhenSecondCall = await usersService.FindOneUserAsync(x => x.Id == user.Id); 152 | 153 | //Assert 154 | Assert.Null(userToAssertWhenFirstCall); 155 | Assert.Equal(userToAssertWhenSecondCall, user); 156 | } 157 | 158 | [Fact] 159 | public async Task Given_ListOfUser_When_AddingUser_Then_CorrectMethodsExecuted() 160 | { 161 | // Arrange 162 | var user = Fixture.Build().Create(); 163 | var usersDb = new Mock>(); 164 | var usersContextMock = new Mock(); 165 | usersContextMock.Setup(x => x.Users).Returns(usersDb.Object); 166 | var usersService = new UsersService(usersContextMock.Object); 167 | 168 | // Act 169 | await usersService.AddUser(user); 170 | 171 | // Assert 172 | usersDb.Verify(x => x.AddAsync(It.Is(y => y == user), CancellationToken.None), Times.Once); 173 | usersContextMock.Verify(x => x.SaveChangesAsync(It.IsAny()), Times.Once); 174 | } 175 | 176 | [Fact] 177 | public async Task Given_UsersWithGlobalFilter_When_GetAllUsersAsync_Then_OnlyFilteredUsersAreReturned() 178 | { 179 | // Arrange 180 | var userJohn = new User { Id = 1, Name = "John" }; 181 | var userJack = new User { Id = 3, Name = "Jack" }; 182 | 183 | var usersContextMock = new Mock(); 184 | usersContextMock.Setup(x => x.Users) 185 | .ReturnsDbSetWithGlobalFilter( 186 | new List { userJohn, userJack }, 187 | user => user.Name == "John" 188 | ); 189 | 190 | var usersService = new UsersService(usersContextMock.Object); 191 | 192 | // Act 193 | var result = await usersService.GetAllUsersAsync(CancellationToken.None); // should exclude userJack 194 | 195 | // Assert 196 | Assert.Single(result); 197 | Assert.Equal(1, result.First().Id); 198 | } 199 | 200 | private static IList GenerateNotLockedUsers() 201 | { 202 | IList users = new List 203 | { 204 | Fixture.Build().With(u => u.AccountLocked, false).Create(), 205 | Fixture.Build().With(u => u.AccountLocked, false).Create() 206 | }; 207 | 208 | return users; 209 | } 210 | 211 | private static IList GenerateEnabledGroups() 212 | { 213 | IList users = new List 214 | { 215 | Fixture.Build().With(u => u.IsEnabled, true).Create(), 216 | Fixture.Build().With(u => u.IsEnabled, true).Create() 217 | }; 218 | 219 | return users; 220 | } 221 | } 222 | } -------------------------------------------------------------------------------- /src/Moq.EntityFrameworkCore.Tests/DbAsyncQueryProvider/InMemoryAsyncEnumerableTests.cs: -------------------------------------------------------------------------------- 1 | namespace Moq.EntityFrameworkCore.Tests.DbAsyncQueryProvider 2 | { 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Linq.Expressions; 6 | using EntityFrameworkCore.DbAsyncQueryProvider; 7 | using Xunit; 8 | 9 | public static class InMemoryAsyncEnumerableTests 10 | { 11 | [Fact] 12 | public static void Given_InMemoryAsyncEnumerable_When_GetAsyncEnumerator_Then_EnumeratorFromInInnerEnumerableShouldBeUsed() 13 | { 14 | // Arrange 15 | var enumerableMock = new Mock>(); 16 | var inMemoryAsyncEnumerable = new InMemoryAsyncEnumerable(enumerableMock.Object); 17 | 18 | // Act 19 | inMemoryAsyncEnumerable.GetAsyncEnumerator(); 20 | 21 | // Assert 22 | enumerableMock.Verify(x => x.GetEnumerator()); 23 | } 24 | 25 | [Fact] 26 | public static void Given_InMemoryAsyncEnumerable_When_GetEnumerator_Then_EnumeratorFromInInnerEnumerableShouldBeUsed() 27 | { 28 | // Arrange 29 | var enumerableMock = new Mock>(); 30 | var inMemoryAsyncEnumerable = new InMemoryAsyncEnumerable(enumerableMock.Object); 31 | 32 | // Act 33 | inMemoryAsyncEnumerable.GetEnumerator(); 34 | 35 | // Assert 36 | enumerableMock.Verify(x => x.GetEnumerator()); 37 | } 38 | 39 | [Fact] 40 | public static void Given_Enumerable_When_ObjectCreated_Then_ObjectCorrectlyBuild() 41 | { 42 | // Arrange 43 | var enumerableMock = new Mock>(); 44 | 45 | // Act 46 | var inMemoryAsyncEnumerable = new InMemoryAsyncEnumerable(enumerableMock.Object); 47 | 48 | // Assert 49 | Assert.Equal(enumerableMock.Object.GetEnumerator(), ((IEnumerable)inMemoryAsyncEnumerable).GetEnumerator()); 50 | } 51 | 52 | [Fact] 53 | public static void Given_Expression_When_ObjectCreated_Then_ObjectCorrectlyBuild() 54 | { 55 | // Arrange 56 | var expressionMock = new Mock().Object; 57 | 58 | // Act 59 | var inMemoryAsyncEnumerable = new InMemoryAsyncEnumerable(expressionMock); 60 | 61 | // Assert 62 | Assert.Equal(expressionMock, ((IQueryable)inMemoryAsyncEnumerable).Expression); 63 | } 64 | 65 | [Fact] 66 | public static void Given_Expression_When_ObjectCreated_Then_ProviderIsCorrect() 67 | { 68 | // Arrange 69 | var expressionMock = new Mock().Object; 70 | IQueryable queryableProvider = new InMemoryAsyncEnumerable(expressionMock); 71 | 72 | // Act 73 | var result = queryableProvider.Provider; 74 | 75 | // Assert 76 | Assert.NotNull(result); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/Moq.EntityFrameworkCore.Tests/DbAsyncQueryProvider/InMemoryAsyncQueryProviderTests.cs: -------------------------------------------------------------------------------- 1 | namespace Moq.EntityFrameworkCore.Tests.DbAsyncQueryProvider 2 | { 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | using System.Threading; 6 | using EntityFrameworkCore.DbAsyncQueryProvider; 7 | using Xunit; 8 | 9 | public class InMemoryAsyncQueryProviderTests 10 | { 11 | private readonly Mock queryProviderMock = new Mock(); 12 | private readonly Expression expression = new Mock().Object; 13 | private readonly InMemoryAsyncQueryProvider inMemoryAsyncQueryProvider; 14 | 15 | public InMemoryAsyncQueryProviderTests() 16 | { 17 | this.inMemoryAsyncQueryProvider = new InMemoryAsyncQueryProvider(this.queryProviderMock.Object); 18 | } 19 | 20 | [Fact] 21 | public void Given_InMemoryAsyncQueryProvider_When_CreatingQuery_Then_CorrectInMemoryAsyncEnumerableIsReturned() 22 | { 23 | // Act 24 | IQueryable result = this.inMemoryAsyncQueryProvider.CreateQuery(this.expression); 25 | 26 | // Assert 27 | Assert.IsType>(result); 28 | Assert.Equal(this.expression, result.Expression); 29 | } 30 | 31 | [Fact] 32 | public void Given_InMemoryAsyncQueryProvider_When_CreatingQueryGeneric_Then_CorrectInMemoryAsyncEnumerableIsReturned() 33 | { 34 | // Act 35 | IQueryable result = this.inMemoryAsyncQueryProvider.CreateQuery(this.expression); 36 | 37 | // Assert 38 | Assert.IsType>(result); 39 | Assert.Equal(this.expression, result.Expression); 40 | } 41 | 42 | [Fact] 43 | public void Given_InMemoryAsyncQueryProvider_When_ExecutingQuery_Then_ExecutionIsDoneAtInnerQueryProvider() 44 | { 45 | // Act 46 | this.inMemoryAsyncQueryProvider.Execute(this.expression); 47 | 48 | // Assert 49 | this.queryProviderMock.Verify(x=> x.Execute(this.expression)); 50 | } 51 | 52 | [Fact] 53 | public void Given_InMemoryAsyncQueryProvider_When_ExecutingQueryGeneric_Then_ExecutionIsDoneAtInnerQueryProvider() 54 | { 55 | // Act 56 | this.inMemoryAsyncQueryProvider.Execute(this.expression); 57 | 58 | // Assert 59 | this.queryProviderMock.Verify(x => x.Execute(this.expression)); 60 | } 61 | 62 | [Fact] 63 | public void Given_InMemoryAsyncQueryProvider_When_ExecutingQueryAsync_Then_ExecutionIsDoneAtInnerQueryProvider() 64 | { 65 | // Act 66 | this.inMemoryAsyncQueryProvider.ExecuteAsync(this.expression); 67 | 68 | // Assert 69 | this.queryProviderMock.Verify(x => x.Execute(this.expression)); 70 | } 71 | 72 | [Fact] 73 | public void Given_InMemoryAsyncQueryProvider_When_ExecutingQueryAsyncWithCancellationToken_Then_ExecutionIsDoneAtInnerQueryProvider() 74 | { 75 | // Act 76 | this.inMemoryAsyncQueryProvider.ExecuteAsync(this.expression, CancellationToken.None); 77 | 78 | // Assert 79 | this.queryProviderMock.Verify(x => x.Execute(this.expression)); 80 | } 81 | 82 | [Fact] 83 | public void Given_InMemoryAsyncQueryProvider_When_ExecutingQueryAsyncAndGeneric_Then_ExecutionIsDoneAtInnerQueryProvider() 84 | { 85 | // Act 86 | this.inMemoryAsyncQueryProvider.ExecuteAsync(this.expression, CancellationToken.None); 87 | 88 | // Assert 89 | this.queryProviderMock.Verify(x => x.Execute(this.expression)); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/Moq.EntityFrameworkCore.Tests/DbAsyncQueryProvider/InMemoryDbAsyncEnumeratorTests.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace Moq.EntityFrameworkCore.Tests.DbAsyncQueryProvider 4 | { 5 | using System.Collections.Generic; 6 | using System.Threading; 7 | using EntityFrameworkCore.DbAsyncQueryProvider; 8 | using Xunit; 9 | 10 | public class InMemoryDbAsyncEnumeratorTests 11 | { 12 | private readonly Mock> enumeratorMock = new Mock>(); 13 | private readonly InMemoryDbAsyncEnumerator inMemoryDbAsyncEnumerator; 14 | 15 | public InMemoryDbAsyncEnumeratorTests() 16 | { 17 | this.inMemoryDbAsyncEnumerator = new InMemoryDbAsyncEnumerator(this.enumeratorMock.Object); 18 | } 19 | 20 | [Fact] 21 | public void Given_InMemoryDbAsyncEnumerator_When_Dispose_Then_InnerEnumeratorShouldBeDisposed() 22 | { 23 | // Act 24 | this.inMemoryDbAsyncEnumerator.Dispose(); 25 | 26 | // Assert 27 | this.enumeratorMock.Verify(x => x.Dispose()); 28 | } 29 | 30 | [Fact] 31 | public void Given_InMemoryDbAsyncEnumerator_When_Current_Then_CurrentFromInInnerEnumeratorShouldBeUsed() 32 | { 33 | // Act 34 | int result = this.inMemoryDbAsyncEnumerator.Current; 35 | 36 | // Assert 37 | this.enumeratorMock.VerifyGet(x=> x.Current); 38 | } 39 | 40 | [Fact] 41 | public async Task Given_InMemoryDbAsyncEnumerator_When_Current_Then_CurrentShouldBeSameAsInInnerEnumerator() 42 | { 43 | // Act 44 | await this.inMemoryDbAsyncEnumerator.MoveNext(CancellationToken.None); 45 | 46 | // Assert 47 | this.enumeratorMock.Verify(x => x.MoveNext()); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Moq.EntityFrameworkCore.Tests/Moq.EntityFrameworkCore.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | all 14 | runtime; build; native; contentfiles; analyzers 15 | 16 | 17 | all 18 | runtime; build; native; contentfiles; analyzers 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/Moq.EntityFrameworkCore.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26730.16 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Moq.EntityFrameworkCore.Tests", "Moq.EntityFrameworkCore.Tests\Moq.EntityFrameworkCore.Tests.csproj", "{2CFFE7E3-7FB7-4976-B76A-F15721BE079B}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Moq.EntityFrameworkCore", "Moq.EntityFrameworkCore\Moq.EntityFrameworkCore.csproj", "{18D4C23D-5754-4C7A-A451-E757BD26B708}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Moq.EntityFrameworkCore.Examples", "Moq.EntityFrameworkCore.Examples\Moq.EntityFrameworkCore.Examples.csproj", "{FFE13C93-4BA3-4907-8086-C6DC9BB81426}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {2CFFE7E3-7FB7-4976-B76A-F15721BE079B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {2CFFE7E3-7FB7-4976-B76A-F15721BE079B}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {2CFFE7E3-7FB7-4976-B76A-F15721BE079B}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {2CFFE7E3-7FB7-4976-B76A-F15721BE079B}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {18D4C23D-5754-4C7A-A451-E757BD26B708}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {18D4C23D-5754-4C7A-A451-E757BD26B708}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {18D4C23D-5754-4C7A-A451-E757BD26B708}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {18D4C23D-5754-4C7A-A451-E757BD26B708}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {FFE13C93-4BA3-4907-8086-C6DC9BB81426}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {FFE13C93-4BA3-4907-8086-C6DC9BB81426}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {FFE13C93-4BA3-4907-8086-C6DC9BB81426}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {FFE13C93-4BA3-4907-8086-C6DC9BB81426}.Release|Any CPU.Build.0 = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(ExtensibilityGlobals) = postSolution 35 | SolutionGuid = {FEA1E4A3-0FB3-4B77-A95E-2F57284266F6} 36 | EndGlobalSection 37 | EndGlobal 38 | -------------------------------------------------------------------------------- /src/Moq.EntityFrameworkCore/DbAsyncQueryProvider/InMemoryAsyncEnumerable.cs: -------------------------------------------------------------------------------- 1 | namespace Moq.EntityFrameworkCore.DbAsyncQueryProvider 2 | { 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Linq.Expressions; 6 | using System.Threading; 7 | 8 | public class InMemoryAsyncEnumerable : EnumerableQuery, IAsyncEnumerable, IQueryable 9 | { 10 | public InMemoryAsyncEnumerable(IEnumerable enumerable) 11 | : base(enumerable) 12 | { 13 | } 14 | 15 | public InMemoryAsyncEnumerable(Expression expression) 16 | : base(expression) 17 | { 18 | } 19 | 20 | IQueryProvider IQueryable.Provider => new InMemoryAsyncQueryProvider(this); 21 | 22 | public IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = new CancellationToken()) 23 | { 24 | return new InMemoryDbAsyncEnumerator(this.AsEnumerable().GetEnumerator()); 25 | } 26 | 27 | public IAsyncEnumerator GetEnumerator() 28 | { 29 | return this.GetAsyncEnumerator(); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Moq.EntityFrameworkCore/DbAsyncQueryProvider/InMemoryAsyncQueryProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Moq.EntityFrameworkCore.DbAsyncQueryProvider 2 | { 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | using Microsoft.EntityFrameworkCore.Query; 8 | 9 | public class InMemoryAsyncQueryProvider : IAsyncQueryProvider 10 | { 11 | private readonly IQueryProvider innerQueryProvider; 12 | 13 | public InMemoryAsyncQueryProvider(IQueryProvider innerQueryProvider) 14 | { 15 | this.innerQueryProvider = innerQueryProvider; 16 | } 17 | 18 | public IQueryable CreateQuery(Expression expression) 19 | { 20 | return new InMemoryAsyncEnumerable(expression); 21 | } 22 | 23 | public IQueryable CreateQuery(Expression expression) 24 | { 25 | return new InMemoryAsyncEnumerable(expression); 26 | } 27 | 28 | public object Execute(Expression expression) 29 | { 30 | return this.innerQueryProvider.Execute(expression); 31 | } 32 | 33 | public TResult Execute(Expression expression) 34 | { 35 | return this.innerQueryProvider.Execute(expression); 36 | } 37 | 38 | public TResult ExecuteAsync(Expression expression, CancellationToken cancellationToken = new CancellationToken()) 39 | { 40 | var result = Execute(expression); 41 | 42 | var expectedResultType = typeof(TResult).GetGenericArguments()?.FirstOrDefault(); 43 | if (expectedResultType == null) 44 | { 45 | return default(TResult); 46 | } 47 | 48 | return (TResult)typeof(Task).GetMethod(nameof(Task.FromResult)) 49 | ?.MakeGenericMethod(expectedResultType) 50 | .Invoke(null, new[] { result }); 51 | } 52 | 53 | 54 | public Task ExecuteAsync(Expression expression, CancellationToken cancellationToken) 55 | { 56 | return Task.FromResult(this.Execute(expression)); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Moq.EntityFrameworkCore/DbAsyncQueryProvider/InMemoryDbAsyncEnumerator.cs: -------------------------------------------------------------------------------- 1 | namespace Moq.EntityFrameworkCore.DbAsyncQueryProvider 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | 8 | public class InMemoryDbAsyncEnumerator : IAsyncEnumerator 9 | { 10 | private readonly IEnumerator innerEnumerator; 11 | private bool disposed = false; 12 | 13 | public InMemoryDbAsyncEnumerator(IEnumerator enumerator) 14 | { 15 | this.innerEnumerator = enumerator; 16 | } 17 | 18 | public void Dispose() 19 | { 20 | this.Dispose(true); 21 | GC.SuppressFinalize(this); 22 | } 23 | 24 | public ValueTask DisposeAsync() 25 | { 26 | Dispose(); 27 | return new ValueTask(); 28 | } 29 | 30 | public Task MoveNext(CancellationToken cancellationToken) 31 | { 32 | return Task.FromResult(this.innerEnumerator.MoveNext()); 33 | } 34 | 35 | public ValueTask MoveNextAsync() 36 | { 37 | return new ValueTask(Task.FromResult(this.innerEnumerator.MoveNext())); 38 | } 39 | 40 | public T Current => this.innerEnumerator.Current; 41 | 42 | protected virtual void Dispose(bool disposing) 43 | { 44 | if (!this.disposed) 45 | { 46 | if (disposing) 47 | { 48 | // Dispose managed resources. 49 | this.innerEnumerator.Dispose(); 50 | } 51 | 52 | this.disposed = true; 53 | } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Moq.EntityFrameworkCore/Dynamic/GlobalFilterDbSetExtensionsDynamic.cs: -------------------------------------------------------------------------------- 1 | namespace Moq.EntityFrameworkCore.Dynamic 2 | { 3 | using Microsoft.EntityFrameworkCore; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using Moq.Language.Flow; 8 | 9 | public static class GlobalFilterDbSetExtensionsDynamic 10 | { 11 | public static IReturnsResult ReturnsDbSetWithGlobalFilterDynamic( 12 | this ISetup> setup, 13 | IEnumerable entities, 14 | Func filter 15 | ) 16 | where TContext : DbContext 17 | where TEntity : class 18 | { 19 | var filtered = entities.Where(filter).ToList(); 20 | return setup.ReturnsDbSetDynamic(filtered); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Moq.EntityFrameworkCore/Dynamic/MoqExtensionsDynamic.cs: -------------------------------------------------------------------------------- 1 | namespace Moq.EntityFrameworkCore.Dynamic 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading; 7 | using Microsoft.EntityFrameworkCore; 8 | using Moq.EntityFrameworkCore.DbAsyncQueryProvider; 9 | using Moq.Language; 10 | using Moq.Language.Flow; 11 | 12 | public static class MoqExtensionsDynamic 13 | { 14 | public static IReturnsResult ReturnsDbSetDynamic(this ISetupGetter> setupResult, IEnumerable entities, Mock> dbSetMock = null) where T : class where TEntity : class 15 | { 16 | dbSetMock = dbSetMock ?? new Mock>(); 17 | 18 | ConfigureMockDynamic(dbSetMock, entities); 19 | 20 | return setupResult.Returns(() => dbSetMock.Object); 21 | } 22 | 23 | public static IReturnsResult ReturnsDbSetDynamic(this ISetup> setupResult, IEnumerable entities, Mock> dbSetMock = null) where T : class where TEntity : class 24 | { 25 | dbSetMock = dbSetMock ?? new Mock>(); 26 | 27 | ConfigureMockDynamic(dbSetMock, entities); 28 | 29 | return setupResult.Returns(() => dbSetMock.Object); 30 | } 31 | 32 | public static ISetupSequentialResult> ReturnsDbSetDynamic(this ISetupSequentialResult> setupResult, IEnumerable entities, Mock> dbSetMock = null) where TEntity : class 33 | { 34 | dbSetMock = dbSetMock ?? new Mock>(); 35 | 36 | ConfigureMockDynamic(dbSetMock, entities); 37 | 38 | return setupResult.Returns(() => dbSetMock.Object); 39 | } 40 | 41 | /// 42 | /// Configures a Mock for a or a so that it can be queriable via LINQ 43 | /// 44 | public static void ConfigureMockDynamic(Mock dbSetMock, IEnumerable entities) where TEntity : class 45 | { 46 | var entitiesAsQueryable = entities.AsQueryable(); 47 | 48 | dbSetMock.As>() 49 | .Setup(m => m.GetAsyncEnumerator(CancellationToken.None)) 50 | .Returns(() => new InMemoryDbAsyncEnumerator(entitiesAsQueryable.GetEnumerator())); 51 | 52 | dbSetMock.As>() 53 | .Setup(m => m.Provider) 54 | .Returns(new InMemoryAsyncQueryProvider(entitiesAsQueryable.Provider)); 55 | 56 | dbSetMock.As>().Setup(m => m.Expression).Returns(entitiesAsQueryable.Expression); 57 | dbSetMock.As>().Setup(m => m.ElementType).Returns(entitiesAsQueryable.ElementType); 58 | dbSetMock.As>().Setup(m => m.GetEnumerator()).Returns(() => entitiesAsQueryable.GetEnumerator()); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/Moq.EntityFrameworkCore/GlobalFilterDbSetExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Moq.EntityFrameworkCore 2 | { 3 | using Microsoft.EntityFrameworkCore; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using Moq.Language.Flow; 8 | 9 | public static class GlobalFilterDbSetExtensions 10 | { 11 | public static IReturnsResult ReturnsDbSetWithGlobalFilter( 12 | this ISetup> setup, 13 | IEnumerable entities, 14 | Func filter 15 | ) 16 | where TContext : DbContext 17 | where TEntity : class 18 | { 19 | var filtered = entities.Where(filter).ToList(); 20 | return setup.ReturnsDbSet(filtered); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Moq.EntityFrameworkCore/Moq.EntityFrameworkCore.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | net8.0 6 | 5.0.0.0 7 | 5.0.2.0 8 | 3.1.2 9 | Michał Jankowski 10 | Moq.EntityFrameworkCore 11 | Library that provides methods that will help you with mocking Entity Framework Core. 12 | Copyright 2024 - Michał Jankowski 13 | MIT 14 | https://github.com/MichalJankowskii/Moq.EntityFrameworkCore 15 | https://github.com/MichalJankowskii/Moq.EntityFrameworkCore 16 | Moq mocking EF EnityFramework DbSet DbContext unit test testing framework assert TDD BDD EntityFrameworkCore EFCore Core 17 | Version 8.0.0.1 18 | Added support for EntityFrameworkCore 8.0 19 | en-US 20 | README.md 21 | 22 | 23 | 24 | 25 | True 26 | \ 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/Moq.EntityFrameworkCore/MoqExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Moq.EntityFrameworkCore 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading; 7 | using Microsoft.EntityFrameworkCore; 8 | using Moq.EntityFrameworkCore.DbAsyncQueryProvider; 9 | using Moq.Language; 10 | using Moq.Language.Flow; 11 | 12 | public static class MoqExtensions 13 | { 14 | public static IReturnsResult ReturnsDbSet(this ISetupGetter> setupResult, IEnumerable entities, Mock> dbSetMock = null) where T : class where TEntity : class 15 | { 16 | dbSetMock = dbSetMock ?? new Mock>(); 17 | 18 | ConfigureMock(dbSetMock, entities); 19 | 20 | return setupResult.Returns(dbSetMock.Object); 21 | } 22 | 23 | public static IReturnsResult ReturnsDbSet(this ISetup> setupResult, IEnumerable entities, Mock> dbSetMock = null) where T : class where TEntity : class 24 | { 25 | dbSetMock = dbSetMock ?? new Mock>(); 26 | 27 | ConfigureMock(dbSetMock, entities); 28 | 29 | return setupResult.Returns(dbSetMock.Object); 30 | } 31 | 32 | public static ISetupSequentialResult> ReturnsDbSet(this ISetupSequentialResult> setupResult, IEnumerable entities, Mock> dbSetMock = null) where TEntity : class 33 | { 34 | dbSetMock = dbSetMock ?? new Mock>(); 35 | 36 | ConfigureMock(dbSetMock, entities); 37 | 38 | return setupResult.Returns(dbSetMock.Object); 39 | } 40 | 41 | /// 42 | /// Configures a Mock for a or a so that it can be queriable via LINQ 43 | /// 44 | public static void ConfigureMock(Mock dbSetMock, IEnumerable entities) where TEntity : class 45 | { 46 | var entitiesAsQueryable = entities.AsQueryable(); 47 | 48 | dbSetMock.As>() 49 | .Setup(m => m.GetAsyncEnumerator(CancellationToken.None)) 50 | .Returns(() => new InMemoryDbAsyncEnumerator(entitiesAsQueryable.GetEnumerator())); 51 | 52 | dbSetMock.As>() 53 | .Setup(m => m.Provider) 54 | .Returns(new InMemoryAsyncQueryProvider(entitiesAsQueryable.Provider)); 55 | 56 | dbSetMock.As>().Setup(m => m.Expression).Returns(entitiesAsQueryable.Expression); 57 | dbSetMock.As>().Setup(m => m.ElementType).Returns(entitiesAsQueryable.ElementType); 58 | dbSetMock.As>().Setup(m => m.GetEnumerator()).Returns(() => entitiesAsQueryable.GetEnumerator()); 59 | } 60 | } 61 | } 62 | --------------------------------------------------------------------------------