Skip to content

Commit 2bcc6e8

Browse files
committed
#88 Fix .AsQueryable calls to the test data set
1 parent 51cface commit 2bcc6e8

File tree

8 files changed

+405
-634
lines changed

8 files changed

+405
-634
lines changed

src/MockQueryable/MockQueryable.FakeItEasy/FakeItEasyExtensions.cs

Lines changed: 80 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -10,95 +10,95 @@
1010

1111
namespace MockQueryable.FakeItEasy
1212
{
13-
public static class FakeItEasyExtensions
14-
{
15-
16-
/// <summary>
17-
/// This method allows you to create a mock DbSet for testing purposes.
18-
/// It is particularly useful when you want to simulate the behavior of Entity Framework Core's DbSet
19-
/// with custom expression handling, such as for testing LINQ queries or database operations.
20-
/// The method takes an IQueryable of the entity type and returns a mocked DbSet that implements
21-
/// both IAsyncEnumerable and IQueryable interfaces, allowing for asynchronous enumeration
22-
/// and LINQ query capabilities.
23-
/// </summary>
24-
/// <typeparam name="TEntity">
25-
/// The type of the entity that the DbSet will represent.
26-
/// </typeparam>
27-
public static DbSet<TEntity> BuildMockDbSet<TEntity>(this ICollection<TEntity> data) where TEntity : class
13+
public static class FakeItEasyExtensions
2814
{
29-
return BuildMockDbSet<TEntity, TestExpressionVisitor>(data);
30-
}
3115

32-
/// <summary>
33-
/// This method allows you to create a mock DbSet for testing purposes.
34-
/// It is particularly useful when you want to simulate the behavior of Entity Framework Core's DbSet
35-
/// with custom expression handling, such as for testing LINQ queries or database operations.
36-
/// The method takes an IQueryable of the entity type and returns a mocked DbSet that implements
37-
/// both IAsyncEnumerable and IQueryable interfaces, allowing for asynchronous enumeration
38-
/// and LINQ query capabilities.
39-
/// </summary>
40-
/// <typeparam name="TEntity">
41-
/// The type of the entity that the DbSet will represent.
42-
/// </typeparam>
43-
/// <typeparam name="TExpressionVisitor">
44-
/// The type of the expression visitor that will be used to process LINQ expressions.
45-
/// Can be used to mock EF Core specific expression handling, such as for ILike expressions.
46-
/// </typeparam>
47-
public static DbSet<TEntity> BuildMockDbSet<TEntity, TExpressionVisitor>(this ICollection<TEntity> data)
48-
where TEntity : class
49-
where TExpressionVisitor : ExpressionVisitor, new()
50-
{
51-
var mock = A.Fake<DbSet<TEntity>>(d => d.Implements<IAsyncEnumerable<TEntity>>().Implements<IQueryable<TEntity>>());
52-
var enumerable = new TestAsyncEnumerableEfCore<TEntity, TExpressionVisitor>(data, entity => data.Remove(entity));
53-
mock.ConfigureQueryableCalls(enumerable, data.AsQueryable());
54-
mock.ConfigureAsyncEnumerableCalls(enumerable);
55-
mock.ConfigureDbSetCalls(data.AsQueryable());
16+
/// <summary>
17+
/// This method allows you to create a mock DbSet for testing purposes.
18+
/// It is particularly useful when you want to simulate the behavior of Entity Framework Core's DbSet
19+
/// with custom expression handling, such as for testing LINQ queries or database operations.
20+
/// The method takes an IQueryable of the entity type and returns a mocked DbSet that implements
21+
/// both IAsyncEnumerable and IQueryable interfaces, allowing for asynchronous enumeration
22+
/// and LINQ query capabilities.
23+
/// </summary>
24+
/// <typeparam name="TEntity">
25+
/// The type of the entity that the DbSet will represent.
26+
/// </typeparam>
27+
public static DbSet<TEntity> BuildMockDbSet<TEntity>(this ICollection<TEntity> data) where TEntity : class
28+
{
29+
return BuildMockDbSet<TEntity, TestExpressionVisitor>(data);
30+
}
5631

57-
if (mock is IAsyncEnumerable<TEntity> asyncEnumerable)
58-
{
59-
A.CallTo(() => asyncEnumerable.GetAsyncEnumerator(A<CancellationToken>.Ignored)).ReturnsLazily(() => enumerable.GetAsyncEnumerator());
60-
}
32+
/// <summary>
33+
/// This method allows you to create a mock DbSet for testing purposes.
34+
/// It is particularly useful when you want to simulate the behavior of Entity Framework Core's DbSet
35+
/// with custom expression handling, such as for testing LINQ queries or database operations.
36+
/// The method takes an IQueryable of the entity type and returns a mocked DbSet that implements
37+
/// both IAsyncEnumerable and IQueryable interfaces, allowing for asynchronous enumeration
38+
/// and LINQ query capabilities.
39+
/// </summary>
40+
/// <typeparam name="TEntity">
41+
/// The type of the entity that the DbSet will represent.
42+
/// </typeparam>
43+
/// <typeparam name="TExpressionVisitor">
44+
/// The type of the expression visitor that will be used to process LINQ expressions.
45+
/// Can be used to mock EF Core specific expression handling, such as for ILike expressions.
46+
/// </typeparam>
47+
public static DbSet<TEntity> BuildMockDbSet<TEntity, TExpressionVisitor>(this ICollection<TEntity> data)
48+
where TEntity : class
49+
where TExpressionVisitor : ExpressionVisitor, new()
50+
{
51+
var mock = A.Fake<DbSet<TEntity>>(d => d.Implements<IAsyncEnumerable<TEntity>>().Implements<IQueryable<TEntity>>());
52+
var enumerable = new TestAsyncEnumerableEfCore<TEntity, TExpressionVisitor>(data, entity => data.Remove(entity));
53+
mock.ConfigureQueryableCalls(enumerable, data.AsQueryable());
54+
mock.ConfigureAsyncEnumerableCalls(enumerable);
55+
mock.ConfigureDbSetCalls(data.AsQueryable());
6156

62-
return mock;
63-
}
57+
if (mock is IAsyncEnumerable<TEntity> asyncEnumerable)
58+
{
59+
A.CallTo(() => asyncEnumerable.GetAsyncEnumerator(A<CancellationToken>.Ignored)).ReturnsLazily(() => enumerable.GetAsyncEnumerator());
60+
}
6461

65-
private static void ConfigureQueryableCalls<TEntity>(
66-
this IQueryable<TEntity> mock,
67-
IQueryProvider queryProvider,
68-
IQueryable<TEntity> data) where TEntity : class
69-
{
70-
A.CallTo(() => mock.Provider).Returns(queryProvider);
71-
A.CallTo(() => mock.Expression).Returns(data?.Expression);
72-
A.CallTo(() => mock.ElementType).Returns(data?.ElementType);
73-
A.CallTo(() => mock.GetEnumerator()).ReturnsLazily(() => data?.GetEnumerator());
74-
}
62+
return mock;
63+
}
7564

76-
private static void ConfigureAsyncEnumerableCalls<TEntity>(
77-
this DbSet<TEntity> mock,
78-
IAsyncEnumerable<TEntity> enumerable) where TEntity : class
79-
{
80-
A.CallTo(() => mock.GetAsyncEnumerator(A<CancellationToken>.Ignored))
81-
.Returns(enumerable.GetAsyncEnumerator());
82-
}
65+
private static void ConfigureQueryableCalls<TEntity>(
66+
this IQueryable<TEntity> mock,
67+
IQueryProvider queryProvider,
68+
IQueryable<TEntity> data) where TEntity : class
69+
{
70+
A.CallTo(() => mock.Provider).Returns(queryProvider);
71+
A.CallTo(() => mock.Expression).Returns(data?.Expression);
72+
A.CallTo(() => mock.ElementType).Returns(data?.ElementType);
73+
A.CallTo(() => mock.GetEnumerator()).ReturnsLazily(() => data?.GetEnumerator());
74+
}
8375

84-
private static void ConfigureDbSetCalls<TEntity>(this DbSet<TEntity> mock, IQueryable<TEntity> data)
85-
where TEntity : class
86-
{
87-
A.CallTo(() => mock.AsQueryable()).Returns(data.AsQueryable());
88-
A.CallTo(() => mock.AsAsyncEnumerable()).ReturnsLazily(args => CreateAsyncMock(data));
89-
}
76+
private static void ConfigureAsyncEnumerableCalls<TEntity>(
77+
this DbSet<TEntity> mock,
78+
IAsyncEnumerable<TEntity> enumerable) where TEntity : class
79+
{
80+
A.CallTo(() => mock.GetAsyncEnumerator(A<CancellationToken>.Ignored))
81+
.Returns(enumerable.GetAsyncEnumerator());
82+
}
9083

91-
private static async IAsyncEnumerable<TEntity> CreateAsyncMock<TEntity>(
92-
this IEnumerable<TEntity> data)
93-
where TEntity : class
94-
{
84+
private static void ConfigureDbSetCalls<TEntity>(this DbSet<TEntity> mock, IQueryable<TEntity> data)
85+
where TEntity : class
86+
{
87+
A.CallTo(() => mock.AsQueryable()).Returns(mock);
88+
A.CallTo(() => mock.AsAsyncEnumerable()).ReturnsLazily(args => CreateAsyncMock(data));
89+
}
90+
91+
private static async IAsyncEnumerable<TEntity> CreateAsyncMock<TEntity>(
92+
this IEnumerable<TEntity> data)
93+
where TEntity : class
94+
{
9595

96-
foreach (var entity in data)
97-
{
98-
yield return entity;
99-
}
96+
foreach (var entity in data)
97+
{
98+
yield return entity;
99+
}
100100

101-
await Task.CompletedTask;
101+
await Task.CompletedTask;
102+
}
102103
}
103-
}
104104
}

src/MockQueryable/MockQueryable.Moq/MoqExtensions.cs

Lines changed: 76 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -10,92 +10,90 @@
1010

1111
namespace MockQueryable.Moq
1212
{
13-
public static class MoqExtensions
14-
{
15-
16-
/// <summary>
17-
/// This method allows you to create a mock DbSet for testing purposes.
18-
/// It is particularly useful when you want to simulate the behavior of Entity Framework Core's DbSet
19-
/// with custom expression handling, such as for testing LINQ queries or database operations.
20-
/// The method takes an IQueryable of the entity type and returns a mocked DbSet that implements
21-
/// both IAsyncEnumerable and IQueryable interfaces, allowing for asynchronous enumeration
22-
/// and LINQ query capabilities.
23-
/// </summary>
24-
/// <typeparam name="TEntity">
25-
/// The type of the entity that the DbSet will represent.
26-
/// </typeparam>
27-
public static Mock<DbSet<TEntity>> BuildMockDbSet<TEntity>(this ICollection<TEntity> data) where TEntity : class
13+
public static class MoqExtensions
2814
{
29-
return BuildMockDbSet<TEntity, TestExpressionVisitor>(data);
30-
}
3115

32-
/// <summary>
33-
/// This method allows you to create a mock DbSet for testing purposes.
34-
/// It is particularly useful when you want to simulate the behavior of Entity Framework Core's DbSet
35-
/// with custom expression handling, such as for testing LINQ queries or database operations.
36-
/// The method takes an IQueryable of the entity type and returns a mocked DbSet that implements
37-
/// both IAsyncEnumerable and IQueryable interfaces, allowing for asynchronous enumeration
38-
/// and LINQ query capabilities.
39-
/// </summary>
40-
/// <typeparam name="TEntity">
41-
/// The type of the entity that the DbSet will represent.
42-
/// </typeparam>
43-
/// <typeparam name="TExpressionVisitor">
44-
/// The type of the expression visitor that will be used to process LINQ expressions.
45-
/// Can be used to mock EF Core specific expression handling, such as for ILike expressions.
46-
/// </typeparam>
47-
public static Mock<DbSet<TEntity>> BuildMockDbSet<TEntity, TExpressionVisitor>(this ICollection<TEntity> data)
48-
where TEntity : class
49-
where TExpressionVisitor : ExpressionVisitor, new()
50-
{
51-
var mock = new Mock<DbSet<TEntity>>();
52-
var enumerable = new TestAsyncEnumerableEfCore<TEntity, TExpressionVisitor>(data, entity => data.Remove(entity));
53-
mock.ConfigureAsyncEnumerableCalls(enumerable);
54-
mock.As<IQueryable<TEntity>>().ConfigureQueryableCalls(enumerable, data.AsQueryable());
55-
mock.As<IAsyncEnumerable<TEntity>>().Setup(x => x.GetAsyncEnumerator(It.IsAny<CancellationToken>())).Returns(() => enumerable.GetAsyncEnumerator());
56-
mock.Setup(m => m.AsQueryable()).Returns(enumerable);
16+
/// <summary>
17+
/// This method allows you to create a mock DbSet for testing purposes.
18+
/// It is particularly useful when you want to simulate the behavior of Entity Framework Core's DbSet
19+
/// with custom expression handling, such as for testing LINQ queries or database operations.
20+
/// The method takes an IQueryable of the entity type and returns a mocked DbSet that implements
21+
/// both IAsyncEnumerable and IQueryable interfaces, allowing for asynchronous enumeration
22+
/// and LINQ query capabilities.
23+
/// </summary>
24+
/// <typeparam name="TEntity">
25+
/// The type of the entity that the DbSet will represent.
26+
/// </typeparam>
27+
public static Mock<DbSet<TEntity>> BuildMockDbSet<TEntity>(this ICollection<TEntity> data) where TEntity : class
28+
{
29+
return BuildMockDbSet<TEntity, TestExpressionVisitor>(data);
30+
}
5731

58-
mock.ConfigureDbSetCalls(data.AsQueryable());
59-
return mock;
60-
}
32+
/// <summary>
33+
/// This method allows you to create a mock DbSet for testing purposes.
34+
/// It is particularly useful when you want to simulate the behavior of Entity Framework Core's DbSet
35+
/// with custom expression handling, such as for testing LINQ queries or database operations.
36+
/// The method takes an IQueryable of the entity type and returns a mocked DbSet that implements
37+
/// both IAsyncEnumerable and IQueryable interfaces, allowing for asynchronous enumeration
38+
/// and LINQ query capabilities.
39+
/// </summary>
40+
/// <typeparam name="TEntity">
41+
/// The type of the entity that the DbSet will represent.
42+
/// </typeparam>
43+
/// <typeparam name="TExpressionVisitor">
44+
/// The type of the expression visitor that will be used to process LINQ expressions.
45+
/// Can be used to mock EF Core specific expression handling, such as for ILike expressions.
46+
/// </typeparam>
47+
public static Mock<DbSet<TEntity>> BuildMockDbSet<TEntity, TExpressionVisitor>(this ICollection<TEntity> data)
48+
where TEntity : class
49+
where TExpressionVisitor : ExpressionVisitor, new()
50+
{
51+
var mock = new Mock<DbSet<TEntity>>();
52+
var enumerable = new TestAsyncEnumerableEfCore<TEntity, TExpressionVisitor>(data, entity => data.Remove(entity));
53+
mock.ConfigureAsyncEnumerableCalls(enumerable);
54+
mock.As<IQueryable<TEntity>>().ConfigureQueryableCalls(enumerable, data.AsQueryable());
55+
mock.As<IAsyncEnumerable<TEntity>>().Setup(x => x.GetAsyncEnumerator(It.IsAny<CancellationToken>())).Returns(() => enumerable.GetAsyncEnumerator());
56+
mock.Setup(m => m.AsQueryable()).Returns(enumerable);
6157

62-
private static void ConfigureDbSetCalls<TEntity>(this Mock<DbSet<TEntity>> mock, IQueryable<TEntity> data)
63-
where TEntity : class
64-
{
65-
mock.Setup(m => m.AsQueryable()).Returns(mock.Object);
66-
mock.Setup(m => m.AsAsyncEnumerable()).Returns(CreateAsyncMock(data));
67-
}
58+
mock.ConfigureDbSetCalls(data.AsQueryable());
59+
return mock;
60+
}
6861

69-
private static void ConfigureQueryableCalls<TEntity>(
70-
this Mock<IQueryable<TEntity>> mock,
71-
IQueryProvider queryProvider,
72-
IQueryable<TEntity> data) where TEntity : class
73-
{
74-
mock.Setup(m => m.Provider).Returns(queryProvider);
75-
mock.Setup(m => m.Expression).Returns(data?.Expression);
76-
mock.Setup(m => m.ElementType).Returns(data?.ElementType);
77-
mock.Setup(m => m.GetEnumerator()).Returns(() => data?.GetEnumerator());
62+
private static void ConfigureDbSetCalls<TEntity>(this Mock<DbSet<TEntity>> mock, IQueryable<TEntity> data)
63+
where TEntity : class
64+
{
65+
mock.Setup(m => m.AsQueryable()).Returns(mock.Object);
66+
mock.Setup(m => m.AsAsyncEnumerable()).Returns(CreateAsyncMock(data));
67+
}
7868

79-
}
69+
private static void ConfigureQueryableCalls<TEntity>(
70+
this Mock<IQueryable<TEntity>> mock,
71+
IQueryProvider queryProvider,
72+
IQueryable<TEntity> data) where TEntity : class
73+
{
74+
mock.Setup(m => m.Provider).Returns(queryProvider);
75+
mock.Setup(m => m.Expression).Returns(data?.Expression);
76+
mock.Setup(m => m.ElementType).Returns(data?.ElementType);
77+
mock.Setup(m => m.GetEnumerator()).Returns(() => data?.GetEnumerator());
78+
}
8079

81-
private static void ConfigureAsyncEnumerableCalls<TEntity>(
82-
this Mock<DbSet<TEntity>> mock,
83-
IAsyncEnumerable<TEntity> enumerable) where TEntity : class
84-
{
85-
mock.Setup(d => d.GetAsyncEnumerator(It.IsAny<CancellationToken>()))
86-
.Returns(() => enumerable.GetAsyncEnumerator());
87-
88-
}
80+
private static void ConfigureAsyncEnumerableCalls<TEntity>(
81+
this Mock<DbSet<TEntity>> mock,
82+
IAsyncEnumerable<TEntity> enumerable) where TEntity : class
83+
{
84+
mock.Setup(d => d.GetAsyncEnumerator(It.IsAny<CancellationToken>()))
85+
.Returns(() => enumerable.GetAsyncEnumerator());
86+
}
8987

90-
private static async IAsyncEnumerable<TEntity> CreateAsyncMock<TEntity>(IEnumerable<TEntity> data)
91-
where TEntity : class
92-
{
93-
foreach (var entity in data)
94-
{
95-
yield return entity;
96-
}
88+
private static async IAsyncEnumerable<TEntity> CreateAsyncMock<TEntity>(IEnumerable<TEntity> data)
89+
where TEntity : class
90+
{
91+
foreach (var entity in data)
92+
{
93+
yield return entity;
94+
}
9795

98-
await Task.CompletedTask;
96+
await Task.CompletedTask;
97+
}
9998
}
100-
}
10199
}

0 commit comments

Comments
 (0)