Skip to content

Commit 8e50a60

Browse files
committed
#93 ExecuteUpdateAsync not suported with SetProperty with Value Expression - fixed
1 parent bd69d5c commit 8e50a60

File tree

11 files changed

+193
-23
lines changed

11 files changed

+193
-23
lines changed

src/MockQueryable/MockQueryable.Core/MockQueryable.Core.csproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@
1414
<PackageTags>Mock EntityFrameworkCore Queryable mock EF UnitTests EntityFrameworkCore</PackageTags>
1515
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
1616
<PackageReleaseNotes>
17-
Upgrade to .Net 10 and EntityFrameworkCore 10
17+
#93 ExecuteUpdateAsync not suported with SetProperty with Value Expression - fixed
1818
</PackageReleaseNotes>
19-
<Version>10.0.0</Version>
20-
<AssemblyVersion>10.0.0.0</AssemblyVersion>
21-
<FileVersion>10.0.0.0</FileVersion>
19+
<Version>10.0.1</Version>
20+
<AssemblyVersion>10.0.0.1</AssemblyVersion>
21+
<FileVersion>10.0.0.1</FileVersion>
2222
<Company></Company>
2323
<PackageLicenseFile>LICENSE</PackageLicenseFile>
2424
<PackageReadmeFile>README.md</PackageReadmeFile>

src/MockQueryable/MockQueryable.EntityFrameworkCore/MockQueryable.EntityFrameworkCore.csproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@
1414
<PackageTags>Mock EntityFrameworkCore Queryable mock EF UnitTests EntityFrameworkCore</PackageTags>
1515
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
1616
<PackageReleaseNotes>
17-
Upgrade to .Net 10 and EntityFrameworkCore 10
17+
#93 ExecuteUpdateAsync not suported with SetProperty with Value Expression - fixed
1818
</PackageReleaseNotes>
19-
<Version>10.0.0</Version>
20-
<AssemblyVersion>10.0.0.0</AssemblyVersion>
21-
<FileVersion>10.0.0.0</FileVersion>
19+
<Version>10.0.1</Version>
20+
<AssemblyVersion>10.0.0.1</AssemblyVersion>
21+
<FileVersion>10.0.0.1</FileVersion>
2222
<Company></Company>
2323
<PackageLicenseFile>LICENSE</PackageLicenseFile>
2424
<PackageReadmeFile>README.md</PackageReadmeFile>

src/MockQueryable/MockQueryable.EntityFrameworkCore/TestQueryProviderEfCore.cs

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -104,14 +104,12 @@ private static void ApplyUpdateChangesToDbSet(IEnumerable<T> affectedItems,
104104
foreach (var element in arrayExpr.Expressions.Cast<NewExpression>())
105105
{
106106
var lambdaExpr = ExtractLambda(element.Arguments[0]);
107-
if (element.Arguments[1] is ConstantExpression constExpr)
108-
{
109-
var value = constExpr.Value;
107+
110108

111-
foreach (var item in affectedItems)
112-
{
113-
SetProperty(item, lambdaExpr, value);
114-
}
109+
foreach (var item in affectedItems)
110+
{
111+
var value = ExtractValue(element.Arguments[1], item);
112+
SetProperty(item, lambdaExpr, value);
115113
}
116114

117115

@@ -120,6 +118,39 @@ private static void ApplyUpdateChangesToDbSet(IEnumerable<T> affectedItems,
120118

121119
}
122120

121+
private static object ExtractValue(Expression expr, T item)
122+
{
123+
124+
if (expr is UnaryExpression { NodeType: ExpressionType.Quote } u)
125+
{
126+
expr = u.Operand;
127+
}
128+
129+
// 1. Simply constants: "Unit Test", 123, DateTime.Now...
130+
if (expr is ConstantExpression constExpr)
131+
return constExpr.Value;
132+
133+
134+
// 2. Lambdas: x => x.DateOfBirth.AddYears(1) or () => DateTime.UtcNow
135+
if (expr is LambdaExpression lambda)
136+
{
137+
var del = lambda.Compile();
138+
139+
return lambda.Parameters.Count switch
140+
{
141+
0 => del.DynamicInvoke(), // () => something
142+
1 => del.DynamicInvoke(item), // x => something with x (item)
143+
_ => throw new InvalidOperationException(
144+
"Supported only lambdas with 0 or 1 params.")
145+
};
146+
}
147+
148+
149+
150+
var lambdaNoParams = Expression.Lambda(expr);
151+
return lambdaNoParams.Compile().DynamicInvoke();
152+
}
153+
123154
private static LambdaExpression ExtractLambda(Expression expr)
124155
{
125156

@@ -168,4 +199,5 @@ private static void SetProperty(T item, LambdaExpression lambda, object value)
168199
prop.SetValue(item, converted);
169200
}
170201

202+
171203
}

src/MockQueryable/MockQueryable.FakeItEasy/MockQueryable.FakeItEasy.csproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@
1414
<PackageTags>Mock EntityFrameworkCore Queryable mock EF UnitTests EntityFrameworkCore</PackageTags>
1515
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
1616
<PackageReleaseNotes>
17-
Upgrade to .Net 10 and EntityFrameworkCore 10
17+
#93 ExecuteUpdateAsync not suported with SetProperty with Value Expression - fixed
1818
</PackageReleaseNotes>
19-
<Version>10.0.0</Version>
20-
<AssemblyVersion>10.0.0.0</AssemblyVersion>
21-
<FileVersion>10.0.0.0</FileVersion>
19+
<Version>10.0.1</Version>
20+
<AssemblyVersion>10.0.0.1</AssemblyVersion>
21+
<FileVersion>10.0.0.1</FileVersion>
2222
<Company></Company>
2323
<PackageLicenseFile>LICENSE</PackageLicenseFile>
2424
<PackageReadmeFile>README.md</PackageReadmeFile>

src/MockQueryable/MockQueryable.Moq/MockQueryable.Moq.csproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@
1414
<PackageTags>Mock EntityFrameworkCore Queryable mock EF UnitTests EntityFrameworkCore</PackageTags>
1515
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
1616
<PackageReleaseNotes>
17-
Upgrade to .Net 10 and EntityFrameworkCore 10
17+
#93 ExecuteUpdateAsync not suported with SetProperty with Value Expression - fixed
1818
</PackageReleaseNotes>
19-
<Version>10.0.0</Version>
20-
<AssemblyVersion>10.0.0.0</AssemblyVersion>
21-
<FileVersion>10.0.0.0</FileVersion>
19+
<Version>10.0.1</Version>
20+
<AssemblyVersion>10.0.0.1</AssemblyVersion>
21+
<FileVersion>10.0.0.1</FileVersion>
2222
<Company></Company>
2323
<PackageLicenseFile>LICENSE</PackageLicenseFile>
2424
<PackageReadmeFile>README.md</PackageReadmeFile>

src/MockQueryable/MockQueryable.Sample/MyService.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ public interface IUserRepository
9898
Task<int> DeleteUserAsync(Guid id);
9999

100100
Task<int> UpdateFirstAndLastNameByIdAsync(Guid id, string firstName);
101+
Task<int> AddYearToDateOfBirth(Guid id);
101102
}
102103

103104
public class UserReport

src/MockQueryable/MockQueryable.Sample/MyServiceFakeItEasyTests.cs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,47 @@ public async Task DbSetCreatedFromCollectionExecuteUpdateAsync_ShouldReturnZero(
375375
Assert.That(expectedLastName, Is.EqualTo(user.LastName));
376376
}
377377

378+
[Test]
379+
public async Task DbSetValueExpressionExecuteUpdateAsync()
380+
{
381+
// arrange
382+
var userId = Guid.NewGuid();
383+
var users = TestDataHelper.CreateUserList(userId);
384+
var valueBeforeChange = users.Single(x => x.Id == userId).DateOfBirth;
385+
386+
var mockDbSet = users.BuildMockDbSet();
387+
var userRepository = new TestDbSetRepository(mockDbSet);
388+
389+
//act
390+
var count = await userRepository.AddYearToDateOfBirth(userId);
391+
392+
//assert
393+
Assert.That(count, Is.EqualTo(1));
394+
var user = users.Single(x => x.Id == userId);
395+
Assert.That(valueBeforeChange.AddYears(1), Is.EqualTo(user.DateOfBirth));
396+
397+
}
378398

379399

400+
[Test]
401+
public async Task DbSetValueSetDateOfBirthExecuteUpdateAsync()
402+
{
403+
// arrange
404+
var userId = Guid.NewGuid();
405+
var users = TestDataHelper.CreateUserList(userId);
406+
var expectedYear = DateTime.Now.Year + 42;
407+
408+
var mockDbSet = users.BuildMockDbSet();
409+
var dbset = mockDbSet;
410+
411+
//act
412+
var count = await dbset.Where(x => x.Id == userId)
413+
.ExecuteUpdateAsync(opt => opt.SetProperty(x => x.DateOfBirth, x => new DateTime(expectedYear, 10, 14, 0, 0, 0)));
414+
415+
//assert
416+
Assert.That(count, Is.EqualTo(1));
417+
var user = users.Single(x => x.Id == userId);
418+
Assert.That(expectedYear, Is.EqualTo(user.DateOfBirth.Year));
419+
420+
}
380421
}

src/MockQueryable/MockQueryable.Sample/MyServiceMoqTests.cs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,51 @@ public async Task DbSetCreatedFromCollectionExecuteUpdateAsync()
394394
Assert.That(expectedName, Is.EqualTo(user.LastName));
395395
}
396396

397+
398+
[Test]
399+
public async Task DbSetValueExpressionExecuteUpdateAsync()
400+
{
401+
// arrange
402+
var userId = Guid.NewGuid();
403+
var users = TestDataHelper.CreateUserList(userId);
404+
var valueBeforeChange = users.Single(x => x.Id == userId).DateOfBirth;
405+
406+
var mockDbSet = users.BuildMockDbSet();
407+
var userRepository = new TestDbSetRepository(mockDbSet.Object);
408+
409+
//act
410+
var count = await userRepository.AddYearToDateOfBirth(userId);
411+
412+
//assert
413+
Assert.That(count, Is.EqualTo(1));
414+
var user = users.Single(x => x.Id == userId);
415+
Assert.That(valueBeforeChange.AddYears(1), Is.EqualTo(user.DateOfBirth));
416+
417+
}
418+
419+
420+
[Test]
421+
public async Task DbSetValueSetDateOfBirthExecuteUpdateAsync()
422+
{
423+
// arrange
424+
var userId = Guid.NewGuid();
425+
var users = TestDataHelper.CreateUserList(userId);
426+
var expectedYear = DateTime.Now.Year + 42;
427+
428+
var mockDbSet = users.BuildMockDbSet();
429+
var dbset = mockDbSet.Object;
430+
431+
//act
432+
var count = await dbset.Where(x => x.Id == userId)
433+
.ExecuteUpdateAsync(opt => opt.SetProperty(x => x.DateOfBirth, x => new DateTime(expectedYear, 10, 14, 0, 0, 0)));
434+
435+
//assert
436+
Assert.That(count, Is.EqualTo(1));
437+
var user = users.Single(x => x.Id == userId);
438+
Assert.That(expectedYear, Is.EqualTo(user.DateOfBirth.Year));
439+
440+
}
441+
397442
[Test]
398443
public async Task DbSetCreatedFromCollectionExecuteUpdateAsync_ShouldReturnZero()
399444
{

src/MockQueryable/MockQueryable.Sample/MyServiceNSubstituteTests.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,5 +440,47 @@ public async Task DbSetCreatedFromCollectionExecuteUpdateAsync_ShouldReturnZero(
440440
Assert.That(expectedLastName, Is.EqualTo(user.LastName));
441441
}
442442

443+
[Test]
444+
public async Task DbSetValueExpressionExecuteUpdateAsync()
445+
{
446+
// arrange
447+
var userId = Guid.NewGuid();
448+
var users = TestDataHelper.CreateUserList(userId);
449+
var valueBeforeChange = users.Single(x => x.Id == userId).DateOfBirth;
450+
451+
var mockDbSet = users.BuildMockDbSet();
452+
var userRepository = new TestDbSetRepository(mockDbSet);
453+
454+
//act
455+
var count = await userRepository.AddYearToDateOfBirth(userId);
456+
457+
//assert
458+
Assert.That(count, Is.EqualTo(1));
459+
var user = users.Single(x => x.Id == userId);
460+
Assert.That(valueBeforeChange.AddYears(1), Is.EqualTo(user.DateOfBirth));
461+
462+
}
443463

464+
[Test]
465+
public async Task DbSetValueSetDateOfBirthExecuteUpdateAsync()
466+
{
467+
// arrange
468+
var userId = Guid.NewGuid();
469+
var users = TestDataHelper.CreateUserList(userId);
470+
var expectedYear = DateTime.Now.Year + 42;
471+
472+
var mockDbSet = users.BuildMockDbSet();
473+
var dbset = mockDbSet;
474+
475+
//act
476+
var count = await dbset.Where(x => x.Id == userId)
477+
.ExecuteUpdateAsync(opt => opt.SetProperty(x => x.DateOfBirth, x => new DateTime(expectedYear, 10, 14, 0, 0, 0)));
478+
479+
//assert
480+
Assert.That(count, Is.EqualTo(1));
481+
var user = users.Single(x => x.Id == userId);
482+
Assert.That(expectedYear, Is.EqualTo(user.DateOfBirth.Year));
483+
484+
}
485+
444486
}

src/MockQueryable/MockQueryable.Sample/SampleLikeExpressionVisitor.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,5 @@ protected override Expression VisitMethodCall(MethodCallExpression node)
4040

4141
return base.VisitMethodCall(node);
4242
}
43+
4344
}

0 commit comments

Comments
 (0)