diff --git a/readme.md b/readme.md index 06d5e21..16f4f62 100644 --- a/readme.md +++ b/readme.md @@ -75,7 +75,7 @@ builder.UseSqlServer(connection); builder.EnableRecording(); var data = new SampleDbContext(builder.Options); ``` -snippet source | anchor +snippet source | anchor `EnableRecording` should only be called in the test context. @@ -103,7 +103,7 @@ await data.Companies await Verify(data.Companies.Count()); ``` -snippet source | anchor +snippet source | anchor Will result in the following verified file: @@ -162,7 +162,7 @@ await Verify(new sql = entries }); ``` -snippet source | anchor +snippet source | anchor @@ -193,7 +193,7 @@ await data2.Companies await Verify(data2.Companies.Count()); ``` -snippet source | anchor +snippet source | anchor @@ -387,7 +387,7 @@ var queryable = data.Companies .Where(_ => _.Content == "value"); await Verify(queryable); ``` -snippet source | anchor +snippet source | anchor Will result in the following verified file: @@ -395,14 +395,26 @@ Will result in the following verified file: ### EF Core - - + + +```txt +[ + { + Content: value + } +] +``` +snippet source | anchor + + + + ```txt SELECT [c].[Id], [c].[Content] FROM [Companies] AS [c] WHERE [c].[Content] = N'value' ``` -snippet source | anchor +snippet source | anchor @@ -549,7 +561,7 @@ To be able to use [WebApplicationFactory](https://docs.microsoft.com/en-us/dotne .Options); }); ``` -snippet source | anchor +snippet source | anchor Then use the same identifier for recording: @@ -565,7 +577,7 @@ var companies = await httpClient.GetFromJsonAsync("/companies"); var entries = EfRecording.FinishRecording(testName); ``` -snippet source | anchor +snippet source | anchor 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 }); ``` -snippet source | anchor +snippet source | anchor diff --git a/src/Verify.EntityFramework.Tests/CoreTests.NestedQueryable.verified.txt b/src/Verify.EntityFramework.Tests/CoreTests.NestedQueryable.verified.txt index 4497d10..b320e1c 100644 --- a/src/Verify.EntityFramework.Tests/CoreTests.NestedQueryable.verified.txt +++ b/src/Verify.EntityFramework.Tests/CoreTests.NestedQueryable.verified.txt @@ -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' \ No newline at end of file +WHERE [c].[Content] = N'value', + Result: [ + { + Content: value + } + ] + } +} \ No newline at end of file diff --git a/src/Verify.EntityFramework.Tests/CoreTests.Queryable#00.verified.txt b/src/Verify.EntityFramework.Tests/CoreTests.Queryable#00.verified.txt new file mode 100644 index 0000000..fa124d9 --- /dev/null +++ b/src/Verify.EntityFramework.Tests/CoreTests.Queryable#00.verified.txt @@ -0,0 +1,5 @@ +[ + { + Content: value + } +] \ No newline at end of file diff --git a/src/Verify.EntityFramework.Tests/CoreTests.Queryable.verified.txt b/src/Verify.EntityFramework.Tests/CoreTests.Queryable#01.verified.txt similarity index 100% rename from src/Verify.EntityFramework.Tests/CoreTests.Queryable.verified.txt rename to src/Verify.EntityFramework.Tests/CoreTests.Queryable#01.verified.txt diff --git a/src/Verify.EntityFramework.Tests/CoreTests.SetSelect#00.verified.txt b/src/Verify.EntityFramework.Tests/CoreTests.SetSelect#00.verified.txt new file mode 100644 index 0000000..fa61c21 --- /dev/null +++ b/src/Verify.EntityFramework.Tests/CoreTests.SetSelect#00.verified.txt @@ -0,0 +1,6 @@ +[ + 1, + 4, + 6, + 7 +] \ No newline at end of file diff --git a/src/Verify.EntityFramework.Tests/CoreTests.SetSelect.verified.txt b/src/Verify.EntityFramework.Tests/CoreTests.SetSelect#01.verified.txt similarity index 100% rename from src/Verify.EntityFramework.Tests/CoreTests.SetSelect.verified.txt rename to src/Verify.EntityFramework.Tests/CoreTests.SetSelect#01.verified.txt diff --git a/src/Verify.EntityFramework.Tests/CoreTests.cs b/src/Verify.EntityFramework.Tests/CoreTests.cs index 4067a32..2da8359 100644 --- a/src/Verify.EntityFramework.Tests/CoreTests.cs +++ b/src/Verify.EntityFramework.Tests/CoreTests.cs @@ -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 diff --git a/src/Verify.EntityFramework/Converters/QueryableConverter.cs b/src/Verify.EntityFramework/Converters/QueryableConverter.cs index 4da3d0d..cd7ac28 100644 --- a/src/Verify.EntityFramework/Converters/QueryableConverter.cs +++ b/src/Verify.EntityFramework/Converters/QueryableConverter.cs @@ -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 ExecuteQueryable(IQueryable queryable) => + queryable.ToList(); + public override bool CanConvert(Type type) => IsQueryable(type); diff --git a/src/Verify.EntityFramework/VerifyEntityFramework.cs b/src/Verify.EntityFramework/VerifyEntityFramework.cs index 20254cd..e304681 100644 --- a/src/Verify.EntityFramework/VerifyEntityFramework.cs +++ b/src/Verify.EntityFramework/VerifyEntityFramework.cs @@ -135,7 +135,14 @@ public static class VerifyEntityFramework static ConversionResult QueryableToSql(object arg, IReadOnlyDictionary 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); } } \ No newline at end of file