From 73daad083cac7303fc850e0b4f31f55c42e02c2f Mon Sep 17 00:00:00 2001 From: Eric Burcham Date: Wed, 20 Sep 2023 11:05:57 -0500 Subject: [PATCH] demonstrate that query interceptors do not fire as expected. --- .../Queries/GetStudentsWithEvents.cs | 12 +++ .../SchoolDomain/Queries/QueryWithEvents.cs | 27 +++++ .../SchoolDomain/SchoolDomain.cs | 8 +- .../TypeInspectionAfterQueryInterceptor.cs | 21 ++++ .../TypeInspectionBeforeQueryInterceptor.cs | 21 ++++ .../TypeInspectionInterceptor.cs | 14 +++ ...yInterceptorsRunsAQueryWithInterceptors.cs | 98 +++++++++++++++++++ 7 files changed, 200 insertions(+), 1 deletion(-) create mode 100644 src/Highway.Data.ReadonlyTests/SchoolDomain/Queries/GetStudentsWithEvents.cs create mode 100644 src/Highway.Data.ReadonlyTests/SchoolDomain/Queries/QueryWithEvents.cs create mode 100644 src/Highway.Data.ReadonlyTests/TypeInspectionAfterQueryInterceptor.cs create mode 100644 src/Highway.Data.ReadonlyTests/TypeInspectionBeforeQueryInterceptor.cs create mode 100644 src/Highway.Data.ReadonlyTests/TypeInspectionInterceptor.cs create mode 100644 src/Highway.Data.ReadonlyTests/WhenADomainRepositoryWithQueryInterceptorsRunsAQueryWithInterceptors.cs diff --git a/src/Highway.Data.ReadonlyTests/SchoolDomain/Queries/GetStudentsWithEvents.cs b/src/Highway.Data.ReadonlyTests/SchoolDomain/Queries/GetStudentsWithEvents.cs new file mode 100644 index 00000000..789c6c06 --- /dev/null +++ b/src/Highway.Data.ReadonlyTests/SchoolDomain/Queries/GetStudentsWithEvents.cs @@ -0,0 +1,12 @@ +using System.Data.Entity; + +namespace Highway.Data.ReadonlyTests +{ + internal class GetStudentsWithEvents : QueryWithEvents + { + public GetStudentsWithEvents() + { + ContextQuery = source => source.AsQueryable().Include(x => x.Grade); + } + } +} \ No newline at end of file diff --git a/src/Highway.Data.ReadonlyTests/SchoolDomain/Queries/QueryWithEvents.cs b/src/Highway.Data.ReadonlyTests/SchoolDomain/Queries/QueryWithEvents.cs new file mode 100644 index 00000000..877a7638 --- /dev/null +++ b/src/Highway.Data.ReadonlyTests/SchoolDomain/Queries/QueryWithEvents.cs @@ -0,0 +1,27 @@ +using Highway.Data.Interceptors.Events; + +namespace Highway.Data.ReadonlyTests +{ + internal abstract class QueryWithEvents : Query + { + protected QueryWithEvents() + { + AfterQuery += OnAfterQuery; + BeforeQuery += OnBeforeQuery; + } + + private void OnBeforeQuery(object sender, BeforeQuery e) + { + BeforeQueryFired = true; + } + + public bool BeforeQueryFired { get; set; } + + private void OnAfterQuery(object sender, AfterQuery e) + { + AfterQueryFired = true; + } + + public bool AfterQueryFired { get; set; } + } +} \ No newline at end of file diff --git a/src/Highway.Data.ReadonlyTests/SchoolDomain/SchoolDomain.cs b/src/Highway.Data.ReadonlyTests/SchoolDomain/SchoolDomain.cs index 7e8fa4e8..6093afa8 100644 --- a/src/Highway.Data.ReadonlyTests/SchoolDomain/SchoolDomain.cs +++ b/src/Highway.Data.ReadonlyTests/SchoolDomain/SchoolDomain.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; using Highway.Data.EventManagement.Interfaces; @@ -6,11 +7,16 @@ namespace Highway.Data.ReadonlyTests { public class SchoolDomain : IDomain { + public SchoolDomain(IEnumerable events = null) + { + Events = events?.ToList(); + } + public string ConnectionString { get; } = Configuration.Instance.TestDatabaseConnectionString; public IContextConfiguration Context { get; } = new DefaultContextConfiguration(); - public List Events { get; } = new(); + public List Events { get; } public IMappingConfiguration Mappings { get; } = new SchoolMapping(); } diff --git a/src/Highway.Data.ReadonlyTests/TypeInspectionAfterQueryInterceptor.cs b/src/Highway.Data.ReadonlyTests/TypeInspectionAfterQueryInterceptor.cs new file mode 100644 index 00000000..dd32997c --- /dev/null +++ b/src/Highway.Data.ReadonlyTests/TypeInspectionAfterQueryInterceptor.cs @@ -0,0 +1,21 @@ +using Highway.Data.EventManagement.Interfaces; +using Highway.Data.Interceptors; +using Highway.Data.Interceptors.Events; + +namespace Highway.Data.ReadonlyTests +{ + public class TypeInspectionAfterQueryInterceptor : TypeInspectionInterceptor, IEventInterceptor + { + public bool AppliesTo(AfterQuery eventArgs) + { + return true; + } + + public InterceptorResult Apply(IDataSource context, AfterQuery eventArgs) + { + InspectedType = eventArgs.Result.GetType(); + + return InterceptorResult.Succeeded(); + } + } +} \ No newline at end of file diff --git a/src/Highway.Data.ReadonlyTests/TypeInspectionBeforeQueryInterceptor.cs b/src/Highway.Data.ReadonlyTests/TypeInspectionBeforeQueryInterceptor.cs new file mode 100644 index 00000000..399d1fe1 --- /dev/null +++ b/src/Highway.Data.ReadonlyTests/TypeInspectionBeforeQueryInterceptor.cs @@ -0,0 +1,21 @@ +using Highway.Data.EventManagement.Interfaces; +using Highway.Data.Interceptors; +using Highway.Data.Interceptors.Events; + +namespace Highway.Data.ReadonlyTests +{ + public class TypeInspectionBeforeQueryInterceptor : TypeInspectionInterceptor, IEventInterceptor + { + public bool AppliesTo(BeforeQuery eventArgs) + { + return true; + } + + public InterceptorResult Apply(IDataSource context, BeforeQuery eventArgs) + { + InspectedType = eventArgs.Query.GetType(); + + return InterceptorResult.Succeeded(); + } + } +} diff --git a/src/Highway.Data.ReadonlyTests/TypeInspectionInterceptor.cs b/src/Highway.Data.ReadonlyTests/TypeInspectionInterceptor.cs new file mode 100644 index 00000000..cf4b70dc --- /dev/null +++ b/src/Highway.Data.ReadonlyTests/TypeInspectionInterceptor.cs @@ -0,0 +1,14 @@ +using System; + +using Highway.Data.EventManagement.Interfaces; + +namespace Highway.Data.ReadonlyTests +{ + public abstract class TypeInspectionInterceptor : IInterceptor + { + public int Priority => -1; + + + public Type InspectedType { get; set; } + } +} \ No newline at end of file diff --git a/src/Highway.Data.ReadonlyTests/WhenADomainRepositoryWithQueryInterceptorsRunsAQueryWithInterceptors.cs b/src/Highway.Data.ReadonlyTests/WhenADomainRepositoryWithQueryInterceptorsRunsAQueryWithInterceptors.cs new file mode 100644 index 00000000..76a3d299 --- /dev/null +++ b/src/Highway.Data.ReadonlyTests/WhenADomainRepositoryWithQueryInterceptorsRunsAQueryWithInterceptors.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections.Generic; +using System.Data.Entity.Infrastructure; + +using FluentAssertions; + +using Highway.Data.EventManagement.Interfaces; +using Highway.Data.Repositories; + +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Highway.Data.ReadonlyTests +{ + [TestClass] + public class WhenADomainRepositoryWithQueryInterceptorsRunsAQueryWithInterceptors + { + private const string ConnectionString = "Data Source=(localDb);Initial Catalog=Highway.Data.Test.Db;Integrated Security=True;Connection Timeout=1"; + + private readonly TypeInspectionAfterQueryInterceptor _afterQueryInterceptor = new TypeInspectionAfterQueryInterceptor(); + + private readonly TypeInspectionBeforeQueryInterceptor _beforeQueryInterceptor = new TypeInspectionBeforeQueryInterceptor(); + + private IEnumerable _results; + + private GetStudentsWithEvents _testQuery; + + [TestInitialize] + public void Setup() + { + // Arrange + // The following code uses a writeable domain context to insert test data. + var domain = new SchoolDomain(); + var domainContext = new DomainContext(domain); + + var firstGrade = new Grade + { + Name = "first", + Section = "section one" + }; + + var bill = new Student + { + DoB = DateTime.Now.Subtract(TimeSpan.FromDays(365)), + Height = 60, + Weight = 180, + Name = "Bill" + }; + + firstGrade.AddStudent(bill); + + domainContext.Add(bill); + domainContext.Commit(); + + // Act + // The following code uses a readonly domain context to query the test data. + var readonlyDomain = new SchoolDomain(new List { _afterQueryInterceptor, _beforeQueryInterceptor }); + var readonlyDomainContext = new ReadonlyDomainContext(readonlyDomain); + var readonlyRepository = new ReadonlyDomainRepository(readonlyDomainContext, readonlyDomain); + _testQuery = new GetStudentsWithEvents(); + _results = readonlyRepository.Find(_testQuery); + } + + [TestMethod] + public void The_Query_After_Query_Interceptor_Should_Fire() + { + // FAILS + _testQuery.AfterQueryFired.Should().BeTrue(); + } + + [TestMethod] + public void The_Query_Before_Query_Interceptor_Should_Fire() + { + // FAILS + _testQuery.BeforeQueryFired.Should().BeTrue(); + } + + [TestMethod] + public void The_Repository_After_Query_Interceptor_Should_Fire() + { + // PASSES + _afterQueryInterceptor.InspectedType.Should().Be(typeof(DbQuery)); + } + + [TestMethod] + public void The_Repository_Before_Query_Interceptor_Should_Fire() + { + // PASSES + _beforeQueryInterceptor.InspectedType.Should().Be(typeof(GetStudentsWithEvents)); + } + + [TestMethod] + public void The_Results_Should_Be_Populated() + { + // PASSES + _results.Should().HaveCountGreaterThan(0); + } + } +}