This commit is contained in:
Simon Cropp 2023-09-05 11:11:01 +10:00 коммит произвёл GitHub
Родитель e406283c28
Коммит 6212cd3da3
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
9 изменённых файлов: 107 добавлений и 19 удалений

Просмотреть файл

@ -75,7 +75,7 @@ builder.UseSqlServer(connection);
builder.EnableRecording();
var data = new SampleDbContext(builder.Options);
```
<sup><a href='/src/Verify.EntityFramework.Tests/CoreTests.cs#L281-L288' title='Snippet source file'>snippet source</a> | <a href='#snippet-enablerecording' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.EntityFramework.Tests/CoreTests.cs#L294-L301' title='Snippet source file'>snippet source</a> | <a href='#snippet-enablerecording' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->
`EnableRecording` should only be called in the test context.
@ -103,7 +103,7 @@ await data.Companies
await Verify(data.Companies.Count());
```
<sup><a href='/src/Verify.EntityFramework.Tests/CoreTests.cs#L378-L395' title='Snippet source file'>snippet source</a> | <a href='#snippet-recording' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.EntityFramework.Tests/CoreTests.cs#L391-L408' title='Snippet source file'>snippet source</a> | <a href='#snippet-recording' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->
Will result in the following verified file:
@ -162,7 +162,7 @@ await Verify(new
sql = entries
});
```
<sup><a href='/src/Verify.EntityFramework.Tests/CoreTests.cs#L503-L526' title='Snippet source file'>snippet source</a> | <a href='#snippet-recordingspecific' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.EntityFramework.Tests/CoreTests.cs#L516-L539' title='Snippet source file'>snippet source</a> | <a href='#snippet-recordingspecific' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->
@ -193,7 +193,7 @@ await data2.Companies
await Verify(data2.Companies.Count());
```
<sup><a href='/src/Verify.EntityFramework.Tests/CoreTests.cs#L347-L369' title='Snippet source file'>snippet source</a> | <a href='#snippet-multidbcontexts' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.EntityFramework.Tests/CoreTests.cs#L360-L382' title='Snippet source file'>snippet source</a> | <a href='#snippet-multidbcontexts' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->
<!-- snippet: CoreTests.MultiDbContexts.verified.txt -->
@ -387,7 +387,7 @@ var queryable = data.Companies
.Where(_ => _.Content == "value");
await Verify(queryable);
```
<sup><a href='/src/Verify.EntityFramework.Tests/CoreTests.cs#L248-L254' title='Snippet source file'>snippet source</a> | <a href='#snippet-queryable' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.EntityFramework.Tests/CoreTests.cs#L253-L259' title='Snippet source file'>snippet source</a> | <a href='#snippet-queryable' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->
Will result in the following verified file:
@ -395,14 +395,26 @@ Will result in the following verified file:
### EF Core
<!-- snippet: CoreTests.Queryable.verified.txt -->
<a id='snippet-CoreTests.Queryable.verified.txt'></a>
<!-- snippet: CoreTests.Queryable#00.verified.txt -->
<a id='snippet-CoreTests.Queryable#00.verified.txt'></a>
```txt
[
{
Content: value
}
]
```
<sup><a href='/src/Verify.EntityFramework.Tests/CoreTests.Queryable#00.verified.txt#L1-L5' title='Snippet source file'>snippet source</a> | <a href='#snippet-CoreTests.Queryable#00.verified.txt' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->
<!-- snippet: CoreTests.Queryable#01.verified.txt -->
<a id='snippet-CoreTests.Queryable#01.verified.txt'></a>
```txt
SELECT [c].[Id], [c].[Content]
FROM [Companies] AS [c]
WHERE [c].[Content] = N'value'
```
<sup><a href='/src/Verify.EntityFramework.Tests/CoreTests.Queryable.verified.txt#L1-L3' title='Snippet source file'>snippet source</a> | <a href='#snippet-CoreTests.Queryable.verified.txt' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.EntityFramework.Tests/CoreTests.Queryable#01.verified.txt#L1-L3' title='Snippet source file'>snippet source</a> | <a href='#snippet-CoreTests.Queryable#01.verified.txt' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->
@ -549,7 +561,7 @@ To be able to use [WebApplicationFactory](https://docs.microsoft.com/en-us/dotne
.Options);
});
```
<sup><a href='/src/Verify.EntityFramework.Tests/CoreTests.cs#L461-L472' title='Snippet source file'>snippet source</a> | <a href='#snippet-enablerecordingwithidentifier' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.EntityFramework.Tests/CoreTests.cs#L474-L485' title='Snippet source file'>snippet source</a> | <a href='#snippet-enablerecordingwithidentifier' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->
Then use the same identifier for recording:
@ -565,7 +577,7 @@ var companies = await httpClient.GetFromJsonAsync<Company[]>("/companies");
var entries = EfRecording.FinishRecording(testName);
```
<sup><a href='/src/Verify.EntityFramework.Tests/CoreTests.cs#L428-L438' title='Snippet source file'>snippet source</a> | <a href='#snippet-recordwithidentifier' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.EntityFramework.Tests/CoreTests.cs#L441-L451' title='Snippet source file'>snippet source</a> | <a href='#snippet-recordwithidentifier' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->
The results will not be automatically included in verified file so it will have to be verified manually:
@ -579,7 +591,7 @@ await Verify(new
sql = entries
});
```
<sup><a href='/src/Verify.EntityFramework.Tests/CoreTests.cs#L440-L448' title='Snippet source file'>snippet source</a> | <a href='#snippet-verifyrecordedcommandswithidentifier' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.EntityFramework.Tests/CoreTests.cs#L453-L461' title='Snippet source file'>snippet source</a> | <a href='#snippet-verifyrecordedcommandswithidentifier' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Просмотреть файл

@ -1,3 +1,13 @@
SELECT [c].[Id], [c].[Content]
{
queryable: {
Sql:
SELECT [c].[Id], [c].[Content]
FROM [Companies] AS [c]
WHERE [c].[Content] = N'value'
WHERE [c].[Content] = N'value',
Result: [
{
Content: value
}
]
}
}

Просмотреть файл

@ -0,0 +1,5 @@
[
{
Content: value
}
]

Просмотреть файл

@ -0,0 +1,6 @@
[
1,
4,
6,
7
]

Просмотреть файл

@ -243,6 +243,11 @@ public class CoreTests
public async Task Queryable()
{
var database = await DbContextBuilder.GetDatabase("Queryable");
await database.AddData(
new Company
{
Content = "value"
});
var data = database.Context;
#region Queryable
@ -269,10 +274,18 @@ public class CoreTests
public async Task NestedQueryable()
{
var database = await DbContextBuilder.GetDatabase("NestedQueryable");
await database.AddData(
new Company
{
Content = "value"
});
var data = database.Context;
var queryable = data.Companies
.Where(_ => _.Content == "value");
await Verify(queryable);
await Verify(new
{
queryable
});
}
// ReSharper disable once UnusedVariable

Просмотреть файл

@ -1,18 +1,53 @@
class QueryableConverter :
WriteOnlyJsonConverter
{
static MethodInfo executeQueryableDefinition;
static QueryableConverter() =>
executeQueryableDefinition = typeof(QueryableConverter).GetMethod("ExecuteQueryable", BindingFlags.NonPublic| BindingFlags.Static)!;
public override void Write(VerifyJsonWriter writer, object data)
{
var sql = QueryToSql(data);
var queryable = (IQueryable) data;
var sql = queryable.ToQueryString();
if(!TryExecuteQueryable(queryable, out var result))
{
writer.Serialize(sql);
return;
}
writer.WriteStartObject();
writer.WritePropertyName("Sql");
writer.Serialize(sql);
writer.WritePropertyName("Result");
writer.Serialize(result);
writer.WriteEndObject();
}
public static string QueryToSql(object data)
public static bool TryExecuteQueryable(IQueryable queryable, [NotNullWhen(true)] out IList? result)
{
var queryable = (IQueryable)data;
return queryable.ToQueryString();
var entityType = queryable.GetType().GenericTypeArguments.First();
var executeQueryable = executeQueryableDefinition.MakeGenericMethod(entityType);
var parameters = new object?[]
{
queryable
};
try
{
result = (IList) executeQueryable.Invoke(null, parameters)!;
return true;
}
catch
{
result = null;
return false;
}
}
static List<T> ExecuteQueryable<T>(IQueryable<T> queryable) =>
queryable.ToList();
public override bool CanConvert(Type type)
=> IsQueryable(type);

Просмотреть файл

@ -135,7 +135,14 @@ public static class VerifyEntityFramework
static ConversionResult QueryableToSql(object arg, IReadOnlyDictionary<string, object> context)
{
var sql = QueryableConverter.QueryToSql(arg);
var queryable = (IQueryable) arg;
var sql = queryable.ToQueryString();
if (QueryableConverter.TryExecuteQueryable(queryable, out var result))
{
return new(result, "txt", sql);
}
return new(null, "txt", sql);
}
}