diff --git a/Docs/pages/02-filters.md b/Docs/pages/02-filters.md index ed9f346e..faafb230 100644 --- a/Docs/pages/02-filters.md +++ b/Docs/pages/02-filters.md @@ -468,14 +468,17 @@ In addition to [access modifiers](#access-modifiers), | handler of exact type | `.OfExactType()` | `.IsOfExactType()` | `.AreOfExactType()` | | abstract / sealed | `.WhichAreAbstract()` / `.WhichAreSealed()` | `.IsAbstract()` / `.IsSealed()` | `.AreAbstract()` / `.AreSealed()` | | static | `.WhichAreStatic()` | `.IsStatic()` | `.AreStatic()` | +| virtual | `.WhichAreVirtual()` | `.IsVirtual()` | `.AreVirtual()` | +| override | `.WhichOverride()` | `.Overrides()` | `.Override()` | The `OfType` / `IsOfType` / `AreOfType` filters and assertions match the event's handler type (its `EventHandlerType`, e.g. `EventHandler`); the `…ExactType` variants match only the exact handler type. Use `OrOfType()` / `OrOfExactType()` to allow several handler types. :::note[Negation] -The `abstract`, `sealed` and `static` rows have a negated form: `WhichAreNot…` on filters and -`IsNot…` / `AreNot…` on assertions (e.g. `WhichAreNotSealed()`, `IsNotSealed()`, `AreNotSealed()`). +The `abstract`, `sealed`, `static` and `virtual` rows have a negated form: `WhichAreNot…` on filters and +`IsNot…` / `AreNot…` on assertions (e.g. `WhichAreNotSealed()`, `IsNotSealed()`, `AreNotSealed()`); +`override` uses `WhichDoNotOverride()` / `DoesNotOverride()` / `DoNotOverride()`. ::: ```csharp diff --git a/Source/aweXpect.Reflection/Filters/EventFilters.WhichAreVirtual.cs b/Source/aweXpect.Reflection/Filters/EventFilters.WhichAreVirtual.cs new file mode 100644 index 00000000..1e0f5913 --- /dev/null +++ b/Source/aweXpect.Reflection/Filters/EventFilters.WhichAreVirtual.cs @@ -0,0 +1,24 @@ +using System.Reflection; +using aweXpect.Reflection.Collections; +using aweXpect.Reflection.Helpers; + +namespace aweXpect.Reflection; + +public static partial class EventFilters +{ + /// + /// Filters for events that are virtual. + /// + public static Filtered.Events WhichAreVirtual(this Filtered.Events @this) + => @this.Which(Filter.Prefix( + eventInfo => eventInfo.IsReallyVirtual(), + "virtual ")); + + /// + /// Filters for events that are not virtual. + /// + public static Filtered.Events WhichAreNotVirtual(this Filtered.Events @this) + => @this.Which(Filter.Prefix( + eventInfo => !eventInfo.IsReallyVirtual(), + "non-virtual ")); +} diff --git a/Source/aweXpect.Reflection/Filters/EventFilters.WhichOverride.cs b/Source/aweXpect.Reflection/Filters/EventFilters.WhichOverride.cs new file mode 100644 index 00000000..7d20bdcb --- /dev/null +++ b/Source/aweXpect.Reflection/Filters/EventFilters.WhichOverride.cs @@ -0,0 +1,24 @@ +using System.Reflection; +using aweXpect.Reflection.Collections; +using aweXpect.Reflection.Helpers; + +namespace aweXpect.Reflection; + +public static partial class EventFilters +{ + /// + /// Filters for events that override a base class event. + /// + public static Filtered.Events WhichOverride(this Filtered.Events @this) + => @this.Which(Filter.Suffix( + eventInfo => eventInfo.IsOverride(), + "which override a base event ")); + + /// + /// Filters for events that do not override a base class event. + /// + public static Filtered.Events WhichDoNotOverride(this Filtered.Events @this) + => @this.Which(Filter.Suffix( + eventInfo => !eventInfo.IsOverride(), + "which do not override a base event ")); +} diff --git a/Source/aweXpect.Reflection/Helpers/EventInfoHelpers.cs b/Source/aweXpect.Reflection/Helpers/EventInfoHelpers.cs index 44a5b4de..c99302e7 100644 --- a/Source/aweXpect.Reflection/Helpers/EventInfoHelpers.cs +++ b/Source/aweXpect.Reflection/Helpers/EventInfoHelpers.cs @@ -102,6 +102,22 @@ public static bool IsReallyAbstract(this EventInfo? eventInfo) public static bool IsReallySealed(this EventInfo? eventInfo) => eventInfo?.AddMethod?.IsFinal == true; + /// + /// Checks if the is virtual (based on its accessor methods). + /// + /// The to check. + /// if the event is virtual; otherwise, . + public static bool IsReallyVirtual(this EventInfo? eventInfo) + => eventInfo?.AddMethod?.IsVirtual == true; + + /// + /// Checks if the overrides a base class event (based on its accessor methods). + /// + /// The to check. + /// if the event overrides a base class event; otherwise, . + public static bool IsOverride(this EventInfo? eventInfo) + => eventInfo?.AddMethod.IsOverride() == true; + /// /// Checks if the is static (based on its accessor methods). /// diff --git a/Source/aweXpect.Reflection/ThatEvent.IsVirtual.cs b/Source/aweXpect.Reflection/ThatEvent.IsVirtual.cs new file mode 100644 index 00000000..36d00a1f --- /dev/null +++ b/Source/aweXpect.Reflection/ThatEvent.IsVirtual.cs @@ -0,0 +1,59 @@ +using System.Reflection; +using System.Text; +using aweXpect.Core; +using aweXpect.Core.Constraints; +using aweXpect.Reflection.Helpers; +using aweXpect.Results; + +namespace aweXpect.Reflection; + +public static partial class ThatEvent +{ + /// + /// Verifies that the is virtual. + /// + public static AndOrResult> IsVirtual( + this IThat subject) + => new(subject.Get().ExpectationBuilder.AddConstraint((it, grammars) + => new IsVirtualConstraint(it, grammars)), + subject); + + /// + /// Verifies that the is not virtual. + /// + public static AndOrResult> IsNotVirtual( + this IThat subject) + => new(subject.Get().ExpectationBuilder.AddConstraint((it, grammars) + => new IsVirtualConstraint(it, grammars).Invert()), + subject); + + private sealed class IsVirtualConstraint(string it, ExpectationGrammars grammars) + : ConstraintResult.WithNotNullValue(it, grammars), + IValueConstraint + { + public ConstraintResult IsMetBy(EventInfo? actual) + { + Actual = actual; + Outcome = actual.IsReallyVirtual() ? Outcome.Success : Outcome.Failure; + return this; + } + + protected override void AppendNormalExpectation(StringBuilder stringBuilder, string? indentation = null) + => stringBuilder.Append("is virtual"); + + protected override void AppendNormalResult(StringBuilder stringBuilder, string? indentation = null) + { + stringBuilder.Append(It).Append(" was non-virtual "); + Formatter.Format(stringBuilder, Actual); + } + + protected override void AppendNegatedExpectation(StringBuilder stringBuilder, string? indentation = null) + => stringBuilder.Append("is not virtual"); + + protected override void AppendNegatedResult(StringBuilder stringBuilder, string? indentation = null) + { + stringBuilder.Append(It).Append(" was virtual "); + Formatter.Format(stringBuilder, Actual); + } + } +} diff --git a/Source/aweXpect.Reflection/ThatEvent.Overrides.cs b/Source/aweXpect.Reflection/ThatEvent.Overrides.cs new file mode 100644 index 00000000..6ef2e2c3 --- /dev/null +++ b/Source/aweXpect.Reflection/ThatEvent.Overrides.cs @@ -0,0 +1,59 @@ +using System.Reflection; +using System.Text; +using aweXpect.Core; +using aweXpect.Core.Constraints; +using aweXpect.Reflection.Helpers; +using aweXpect.Results; + +namespace aweXpect.Reflection; + +public static partial class ThatEvent +{ + /// + /// Verifies that the overrides a base class event. + /// + public static AndOrResult> Overrides( + this IThat subject) + => new(subject.Get().ExpectationBuilder.AddConstraint((it, grammars) + => new OverridesConstraint(it, grammars)), + subject); + + /// + /// Verifies that the does not override a base class event. + /// + public static AndOrResult> DoesNotOverride( + this IThat subject) + => new(subject.Get().ExpectationBuilder.AddConstraint((it, grammars) + => new OverridesConstraint(it, grammars).Invert()), + subject); + + private sealed class OverridesConstraint(string it, ExpectationGrammars grammars) + : ConstraintResult.WithNotNullValue(it, grammars), + IValueConstraint + { + public ConstraintResult IsMetBy(EventInfo? actual) + { + Actual = actual; + Outcome = actual.IsOverride() ? Outcome.Success : Outcome.Failure; + return this; + } + + protected override void AppendNormalExpectation(StringBuilder stringBuilder, string? indentation = null) + => stringBuilder.Append("overrides a base event"); + + protected override void AppendNormalResult(StringBuilder stringBuilder, string? indentation = null) + { + stringBuilder.Append(It).Append(" did not override a base event "); + Formatter.Format(stringBuilder, Actual); + } + + protected override void AppendNegatedExpectation(StringBuilder stringBuilder, string? indentation = null) + => stringBuilder.Append("does not override a base event"); + + protected override void AppendNegatedResult(StringBuilder stringBuilder, string? indentation = null) + { + stringBuilder.Append(It).Append(" did override a base event "); + Formatter.Format(stringBuilder, Actual); + } + } +} diff --git a/Source/aweXpect.Reflection/ThatEvents.AreVirtual.cs b/Source/aweXpect.Reflection/ThatEvents.AreVirtual.cs new file mode 100644 index 00000000..4cc6bfb2 --- /dev/null +++ b/Source/aweXpect.Reflection/ThatEvents.AreVirtual.cs @@ -0,0 +1,128 @@ +using System.Collections.Generic; +using System.Reflection; +using System.Text; +using aweXpect.Core; +using aweXpect.Core.Constraints; +using aweXpect.Reflection.Helpers; +using aweXpect.Results; +#if NET8_0_OR_GREATER +using System.Threading; +using System.Threading.Tasks; +#endif + +// ReSharper disable PossibleMultipleEnumeration + +namespace aweXpect.Reflection; + +public static partial class ThatEvents +{ + /// + /// Verifies that all items in the filtered collection of are virtual. + /// + public static AndOrResult, IThat>> AreVirtual( + this IThat> subject) + => new(subject.Get().ExpectationBuilder.AddConstraint>((it, grammars) + => new AreVirtualConstraint(it, grammars)), + subject); + +#if NET8_0_OR_GREATER + /// + /// Verifies that all items in the filtered collection of are virtual. + /// + public static AndOrResult, IThat>> AreVirtual( + this IThat> subject) + => new(subject.Get().ExpectationBuilder.AddConstraint>((it, grammars) + => new AreVirtualConstraint(it, grammars)), + subject); +#endif + + /// + /// Verifies that all items in the filtered collection of are not virtual. + /// + public static AndOrResult, IThat>> AreNotVirtual( + this IThat> subject) + => new(subject.Get().ExpectationBuilder.AddConstraint>((it, grammars) + => new AreNotVirtualConstraint(it, grammars)), + subject); + +#if NET8_0_OR_GREATER + /// + /// Verifies that all items in the filtered collection of are not virtual. + /// + public static AndOrResult, IThat>> AreNotVirtual( + this IThat> subject) + => new(subject.Get().ExpectationBuilder.AddConstraint>((it, grammars) + => new AreNotVirtualConstraint(it, grammars)), + subject); +#endif + + private sealed class AreVirtualConstraint(string it, ExpectationGrammars grammars) + : CollectionConstraintResult(grammars), + IValueConstraint> +#if NET8_0_OR_GREATER + , IAsyncConstraint> +#endif + { +#if NET8_0_OR_GREATER + public async Task IsMetBy(IAsyncEnumerable actual, + CancellationToken cancellationToken) + => await SetAsyncValue(actual, @event => @event.IsReallyVirtual()); +#endif + + public ConstraintResult IsMetBy(IEnumerable actual) + => SetValue(actual, @event => @event.IsReallyVirtual()); + + protected override void AppendNormalExpectation(StringBuilder stringBuilder, string? indentation = null) + => stringBuilder.Append("are all virtual"); + + protected override void AppendNormalResult(StringBuilder stringBuilder, string? indentation = null) + { + stringBuilder.Append(it).Append(" contained non-virtual events "); + Formatter.Format(stringBuilder, NotMatching, FormattingOptions.Indented(indentation)); + } + + protected override void AppendNegatedExpectation(StringBuilder stringBuilder, string? indentation = null) + => stringBuilder.Append("are not all virtual"); + + protected override void AppendNegatedResult(StringBuilder stringBuilder, string? indentation = null) + { + stringBuilder.Append(it).Append(" only contained virtual events "); + Formatter.Format(stringBuilder, Matching, FormattingOptions.Indented(indentation)); + } + } + + private sealed class AreNotVirtualConstraint(string it, ExpectationGrammars grammars) + : CollectionConstraintResult(grammars), + IValueConstraint> +#if NET8_0_OR_GREATER + , IAsyncConstraint> +#endif + { +#if NET8_0_OR_GREATER + public async Task IsMetBy(IAsyncEnumerable actual, + CancellationToken cancellationToken) + => await SetAsyncValue(actual, @event => !@event.IsReallyVirtual()); +#endif + + public ConstraintResult IsMetBy(IEnumerable actual) + => SetValue(actual, @event => !@event.IsReallyVirtual()); + + protected override void AppendNormalExpectation(StringBuilder stringBuilder, string? indentation = null) + => stringBuilder.Append("are all not virtual"); + + protected override void AppendNormalResult(StringBuilder stringBuilder, string? indentation = null) + { + stringBuilder.Append(it).Append(" contained virtual events "); + Formatter.Format(stringBuilder, NotMatching, FormattingOptions.Indented(indentation)); + } + + protected override void AppendNegatedExpectation(StringBuilder stringBuilder, string? indentation = null) + => stringBuilder.Append("also contain a virtual event"); + + protected override void AppendNegatedResult(StringBuilder stringBuilder, string? indentation = null) + { + stringBuilder.Append(it).Append(" only contained non-virtual events "); + Formatter.Format(stringBuilder, Matching, FormattingOptions.Indented(indentation)); + } + } +} diff --git a/Source/aweXpect.Reflection/ThatEvents.Override.cs b/Source/aweXpect.Reflection/ThatEvents.Override.cs new file mode 100644 index 00000000..202a23ba --- /dev/null +++ b/Source/aweXpect.Reflection/ThatEvents.Override.cs @@ -0,0 +1,130 @@ +using System.Collections.Generic; +using System.Reflection; +using System.Text; +using aweXpect.Core; +using aweXpect.Core.Constraints; +using aweXpect.Reflection.Helpers; +using aweXpect.Results; +#if NET8_0_OR_GREATER +using System.Threading; +using System.Threading.Tasks; +#endif + +// ReSharper disable PossibleMultipleEnumeration + +namespace aweXpect.Reflection; + +public static partial class ThatEvents +{ + /// + /// Verifies that all items in the filtered collection of override a base class event. + /// + public static AndOrResult, IThat>> Override( + this IThat> subject) + => new(subject.Get().ExpectationBuilder.AddConstraint>((it, grammars) + => new OverrideConstraint(it, grammars)), + subject); + +#if NET8_0_OR_GREATER + /// + /// Verifies that all items in the filtered collection of override a base class event. + /// + public static AndOrResult, IThat>> Override( + this IThat> subject) + => new(subject.Get().ExpectationBuilder.AddConstraint>((it, grammars) + => new OverrideConstraint(it, grammars)), + subject); +#endif + + /// + /// Verifies that all items in the filtered collection of do not override a base class + /// event. + /// + public static AndOrResult, IThat>> DoNotOverride( + this IThat> subject) + => new(subject.Get().ExpectationBuilder.AddConstraint>((it, grammars) + => new DoNotOverrideConstraint(it, grammars)), + subject); + +#if NET8_0_OR_GREATER + /// + /// Verifies that all items in the filtered collection of do not override a base class + /// event. + /// + public static AndOrResult, IThat>> DoNotOverride( + this IThat> subject) + => new(subject.Get().ExpectationBuilder.AddConstraint>((it, grammars) + => new DoNotOverrideConstraint(it, grammars)), + subject); +#endif + + private sealed class OverrideConstraint(string it, ExpectationGrammars grammars) + : CollectionConstraintResult(grammars), + IValueConstraint> +#if NET8_0_OR_GREATER + , IAsyncConstraint> +#endif + { +#if NET8_0_OR_GREATER + public async Task IsMetBy(IAsyncEnumerable actual, + CancellationToken cancellationToken) + => await SetAsyncValue(actual, @event => @event.IsOverride()); +#endif + + public ConstraintResult IsMetBy(IEnumerable actual) + => SetValue(actual, @event => @event.IsOverride()); + + protected override void AppendNormalExpectation(StringBuilder stringBuilder, string? indentation = null) + => stringBuilder.Append("all override a base event"); + + protected override void AppendNormalResult(StringBuilder stringBuilder, string? indentation = null) + { + stringBuilder.Append(it).Append(" contained events which do not override a base event "); + Formatter.Format(stringBuilder, NotMatching, FormattingOptions.Indented(indentation)); + } + + protected override void AppendNegatedExpectation(StringBuilder stringBuilder, string? indentation = null) + => stringBuilder.Append("do not all override a base event"); + + protected override void AppendNegatedResult(StringBuilder stringBuilder, string? indentation = null) + { + stringBuilder.Append(it).Append(" only contained events which override a base event "); + Formatter.Format(stringBuilder, Matching, FormattingOptions.Indented(indentation)); + } + } + + private sealed class DoNotOverrideConstraint(string it, ExpectationGrammars grammars) + : CollectionConstraintResult(grammars), + IValueConstraint> +#if NET8_0_OR_GREATER + , IAsyncConstraint> +#endif + { +#if NET8_0_OR_GREATER + public async Task IsMetBy(IAsyncEnumerable actual, + CancellationToken cancellationToken) + => await SetAsyncValue(actual, @event => !@event.IsOverride()); +#endif + + public ConstraintResult IsMetBy(IEnumerable actual) + => SetValue(actual, @event => !@event.IsOverride()); + + protected override void AppendNormalExpectation(StringBuilder stringBuilder, string? indentation = null) + => stringBuilder.Append("all do not override a base event"); + + protected override void AppendNormalResult(StringBuilder stringBuilder, string? indentation = null) + { + stringBuilder.Append(it).Append(" contained events which override a base event "); + Formatter.Format(stringBuilder, NotMatching, FormattingOptions.Indented(indentation)); + } + + protected override void AppendNegatedExpectation(StringBuilder stringBuilder, string? indentation = null) + => stringBuilder.Append("also contain an event which overrides a base event"); + + protected override void AppendNegatedResult(StringBuilder stringBuilder, string? indentation = null) + { + stringBuilder.Append(it).Append(" only contained events which do not override a base event "); + Formatter.Format(stringBuilder, Matching, FormattingOptions.Indented(indentation)); + } + } +} diff --git a/Tests/aweXpect.Reflection.Api.Tests/Expected/aweXpect.Reflection_net10.0.txt b/Tests/aweXpect.Reflection.Api.Tests/Expected/aweXpect.Reflection_net10.0.txt index 9c3006e3..6f2b07e5 100644 --- a/Tests/aweXpect.Reflection.Api.Tests/Expected/aweXpect.Reflection_net10.0.txt +++ b/Tests/aweXpect.Reflection.Api.Tests/Expected/aweXpect.Reflection_net10.0.txt @@ -229,6 +229,7 @@ namespace aweXpect.Reflection public static aweXpect.Reflection.Collections.Filtered.Events WhichAreNotPublic(this aweXpect.Reflection.Collections.Filtered.Events @this) { } public static aweXpect.Reflection.Collections.Filtered.Events WhichAreNotSealed(this aweXpect.Reflection.Collections.Filtered.Events @this) { } public static aweXpect.Reflection.Collections.Filtered.Events WhichAreNotStatic(this aweXpect.Reflection.Collections.Filtered.Events @this) { } + public static aweXpect.Reflection.Collections.Filtered.Events WhichAreNotVirtual(this aweXpect.Reflection.Collections.Filtered.Events @this) { } public static aweXpect.Reflection.Collections.Filtered.Events WhichAreObsolete(this aweXpect.Reflection.Collections.Filtered.Events @this) { } public static aweXpect.Reflection.Collections.Filtered.Events WhichArePrivate(this aweXpect.Reflection.Collections.Filtered.Events @this) { } public static aweXpect.Reflection.Collections.Filtered.Events WhichArePrivateProtected(this aweXpect.Reflection.Collections.Filtered.Events @this) { } @@ -237,6 +238,9 @@ namespace aweXpect.Reflection public static aweXpect.Reflection.Collections.Filtered.Events WhichArePublic(this aweXpect.Reflection.Collections.Filtered.Events @this) { } public static aweXpect.Reflection.Collections.Filtered.Events WhichAreSealed(this aweXpect.Reflection.Collections.Filtered.Events @this) { } public static aweXpect.Reflection.Collections.Filtered.Events WhichAreStatic(this aweXpect.Reflection.Collections.Filtered.Events @this) { } + public static aweXpect.Reflection.Collections.Filtered.Events WhichAreVirtual(this aweXpect.Reflection.Collections.Filtered.Events @this) { } + public static aweXpect.Reflection.Collections.Filtered.Events WhichDoNotOverride(this aweXpect.Reflection.Collections.Filtered.Events @this) { } + public static aweXpect.Reflection.Collections.Filtered.Events WhichOverride(this aweXpect.Reflection.Collections.Filtered.Events @this) { } public static aweXpect.Reflection.EventFilters.EventsWith With(this aweXpect.Reflection.Collections.Filtered.Events @this, bool inherit = true) where TAttribute : System.Attribute { } public static aweXpect.Reflection.EventFilters.EventsWith With(this aweXpect.Reflection.Collections.Filtered.Events @this, System.Func? predicate, bool inherit = true, [System.Runtime.CompilerServices.CallerArgumentExpression("predicate")] string doNotPopulateThisValue = "") @@ -944,6 +948,7 @@ namespace aweXpect.Reflection { public static aweXpect.Results.AndOrResult> DoesNotHave(this aweXpect.Core.IThat subject, bool inherit = true) where TAttribute : System.Attribute { } + public static aweXpect.Results.AndOrResult> DoesNotOverride(this aweXpect.Core.IThat subject) { } public static aweXpect.Reflection.Results.HasAttributeResult Has(this aweXpect.Core.IThat subject, bool inherit = true) where TAttribute : System.Attribute { } public static aweXpect.Reflection.Results.HasAttributeResult Has(this aweXpect.Core.IThat subject, System.Func predicate, bool inherit = true, [System.Runtime.CompilerServices.CallerArgumentExpression("predicate")] string doNotPopulateThisValue = "") @@ -952,12 +957,15 @@ namespace aweXpect.Reflection public static aweXpect.Results.AndOrResult> IsNotAbstract(this aweXpect.Core.IThat subject) { } public static aweXpect.Results.AndOrResult> IsNotSealed(this aweXpect.Core.IThat subject) { } public static aweXpect.Results.AndOrResult> IsNotStatic(this aweXpect.Core.IThat subject) { } + public static aweXpect.Results.AndOrResult> IsNotVirtual(this aweXpect.Core.IThat subject) { } public static aweXpect.Reflection.ThatEvent.EventOfTypeResult> IsOfExactType(this aweXpect.Core.IThat subject, System.Type handlerType) { } public static aweXpect.Reflection.ThatEvent.EventOfTypeResult> IsOfExactType(this aweXpect.Core.IThat subject) { } public static aweXpect.Reflection.ThatEvent.EventOfTypeResult> IsOfType(this aweXpect.Core.IThat subject, System.Type handlerType) { } public static aweXpect.Reflection.ThatEvent.EventOfTypeResult> IsOfType(this aweXpect.Core.IThat subject) { } public static aweXpect.Results.AndOrResult> IsSealed(this aweXpect.Core.IThat subject) { } public static aweXpect.Results.AndOrResult> IsStatic(this aweXpect.Core.IThat subject) { } + public static aweXpect.Results.AndOrResult> IsVirtual(this aweXpect.Core.IThat subject) { } + public static aweXpect.Results.AndOrResult> Overrides(this aweXpect.Core.IThat subject) { } public sealed class EventOfTypeResult : aweXpect.Results.AndOrResult, aweXpect.Core.IOptionsProvider where TResult : aweXpect.Core.IThat { @@ -978,6 +986,8 @@ namespace aweXpect.Reflection public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> AreNotSealed(this aweXpect.Core.IThat> subject) { } public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> AreNotStatic(this aweXpect.Core.IThat> subject) { } public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> AreNotStatic(this aweXpect.Core.IThat> subject) { } + public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> AreNotVirtual(this aweXpect.Core.IThat> subject) { } + public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> AreNotVirtual(this aweXpect.Core.IThat> subject) { } public static aweXpect.Reflection.ThatEvents.EventsOfTypeResult, aweXpect.Core.IThat>> AreOfExactType(this aweXpect.Core.IThat> subject, System.Type handlerType) { } public static aweXpect.Reflection.ThatEvents.EventsOfTypeResult, aweXpect.Core.IThat>> AreOfExactType(this aweXpect.Core.IThat> subject, System.Type handlerType) { } public static aweXpect.Reflection.ThatEvents.EventsOfTypeResult, aweXpect.Core.IThat>> AreOfExactType(this aweXpect.Core.IThat> subject) { } @@ -990,10 +1000,14 @@ namespace aweXpect.Reflection public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> AreSealed(this aweXpect.Core.IThat> subject) { } public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> AreStatic(this aweXpect.Core.IThat> subject) { } public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> AreStatic(this aweXpect.Core.IThat> subject) { } + public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> AreVirtual(this aweXpect.Core.IThat> subject) { } + public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> AreVirtual(this aweXpect.Core.IThat> subject) { } public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> DoNotHave(this aweXpect.Core.IThat> subject, bool inherit = true) where TAttribute : System.Attribute { } public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> DoNotHave(this aweXpect.Core.IThat> subject, bool inherit = true) where TAttribute : System.Attribute { } + public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> DoNotOverride(this aweXpect.Core.IThat> subject) { } + public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> DoNotOverride(this aweXpect.Core.IThat> subject) { } public static aweXpect.Reflection.Results.HaveAttributeResult> Have(this aweXpect.Core.IThat> subject, bool inherit = true) where TAttribute : System.Attribute { } public static aweXpect.Reflection.Results.HaveAttributeResult> Have(this aweXpect.Core.IThat> subject, bool inherit = true) @@ -1002,6 +1016,8 @@ namespace aweXpect.Reflection where TAttribute : System.Attribute { } public static aweXpect.Reflection.Results.HaveAttributeResult> Have(this aweXpect.Core.IThat> subject, System.Func predicate, bool inherit = true, [System.Runtime.CompilerServices.CallerArgumentExpression("predicate")] string doNotPopulateThisValue = "") where TAttribute : System.Attribute { } + public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> Override(this aweXpect.Core.IThat> subject) { } + public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> Override(this aweXpect.Core.IThat> subject) { } public sealed class EventsOfTypeResult : aweXpect.Results.AndOrResult, aweXpect.Core.IOptionsProvider where TResult : aweXpect.Core.IThat { diff --git a/Tests/aweXpect.Reflection.Api.Tests/Expected/aweXpect.Reflection_net8.0.txt b/Tests/aweXpect.Reflection.Api.Tests/Expected/aweXpect.Reflection_net8.0.txt index 2f460584..52ae5565 100644 --- a/Tests/aweXpect.Reflection.Api.Tests/Expected/aweXpect.Reflection_net8.0.txt +++ b/Tests/aweXpect.Reflection.Api.Tests/Expected/aweXpect.Reflection_net8.0.txt @@ -229,6 +229,7 @@ namespace aweXpect.Reflection public static aweXpect.Reflection.Collections.Filtered.Events WhichAreNotPublic(this aweXpect.Reflection.Collections.Filtered.Events @this) { } public static aweXpect.Reflection.Collections.Filtered.Events WhichAreNotSealed(this aweXpect.Reflection.Collections.Filtered.Events @this) { } public static aweXpect.Reflection.Collections.Filtered.Events WhichAreNotStatic(this aweXpect.Reflection.Collections.Filtered.Events @this) { } + public static aweXpect.Reflection.Collections.Filtered.Events WhichAreNotVirtual(this aweXpect.Reflection.Collections.Filtered.Events @this) { } public static aweXpect.Reflection.Collections.Filtered.Events WhichAreObsolete(this aweXpect.Reflection.Collections.Filtered.Events @this) { } public static aweXpect.Reflection.Collections.Filtered.Events WhichArePrivate(this aweXpect.Reflection.Collections.Filtered.Events @this) { } public static aweXpect.Reflection.Collections.Filtered.Events WhichArePrivateProtected(this aweXpect.Reflection.Collections.Filtered.Events @this) { } @@ -237,6 +238,9 @@ namespace aweXpect.Reflection public static aweXpect.Reflection.Collections.Filtered.Events WhichArePublic(this aweXpect.Reflection.Collections.Filtered.Events @this) { } public static aweXpect.Reflection.Collections.Filtered.Events WhichAreSealed(this aweXpect.Reflection.Collections.Filtered.Events @this) { } public static aweXpect.Reflection.Collections.Filtered.Events WhichAreStatic(this aweXpect.Reflection.Collections.Filtered.Events @this) { } + public static aweXpect.Reflection.Collections.Filtered.Events WhichAreVirtual(this aweXpect.Reflection.Collections.Filtered.Events @this) { } + public static aweXpect.Reflection.Collections.Filtered.Events WhichDoNotOverride(this aweXpect.Reflection.Collections.Filtered.Events @this) { } + public static aweXpect.Reflection.Collections.Filtered.Events WhichOverride(this aweXpect.Reflection.Collections.Filtered.Events @this) { } public static aweXpect.Reflection.EventFilters.EventsWith With(this aweXpect.Reflection.Collections.Filtered.Events @this, bool inherit = true) where TAttribute : System.Attribute { } public static aweXpect.Reflection.EventFilters.EventsWith With(this aweXpect.Reflection.Collections.Filtered.Events @this, System.Func? predicate, bool inherit = true, [System.Runtime.CompilerServices.CallerArgumentExpression("predicate")] string doNotPopulateThisValue = "") @@ -944,6 +948,7 @@ namespace aweXpect.Reflection { public static aweXpect.Results.AndOrResult> DoesNotHave(this aweXpect.Core.IThat subject, bool inherit = true) where TAttribute : System.Attribute { } + public static aweXpect.Results.AndOrResult> DoesNotOverride(this aweXpect.Core.IThat subject) { } public static aweXpect.Reflection.Results.HasAttributeResult Has(this aweXpect.Core.IThat subject, bool inherit = true) where TAttribute : System.Attribute { } public static aweXpect.Reflection.Results.HasAttributeResult Has(this aweXpect.Core.IThat subject, System.Func predicate, bool inherit = true, [System.Runtime.CompilerServices.CallerArgumentExpression("predicate")] string doNotPopulateThisValue = "") @@ -952,12 +957,15 @@ namespace aweXpect.Reflection public static aweXpect.Results.AndOrResult> IsNotAbstract(this aweXpect.Core.IThat subject) { } public static aweXpect.Results.AndOrResult> IsNotSealed(this aweXpect.Core.IThat subject) { } public static aweXpect.Results.AndOrResult> IsNotStatic(this aweXpect.Core.IThat subject) { } + public static aweXpect.Results.AndOrResult> IsNotVirtual(this aweXpect.Core.IThat subject) { } public static aweXpect.Reflection.ThatEvent.EventOfTypeResult> IsOfExactType(this aweXpect.Core.IThat subject, System.Type handlerType) { } public static aweXpect.Reflection.ThatEvent.EventOfTypeResult> IsOfExactType(this aweXpect.Core.IThat subject) { } public static aweXpect.Reflection.ThatEvent.EventOfTypeResult> IsOfType(this aweXpect.Core.IThat subject, System.Type handlerType) { } public static aweXpect.Reflection.ThatEvent.EventOfTypeResult> IsOfType(this aweXpect.Core.IThat subject) { } public static aweXpect.Results.AndOrResult> IsSealed(this aweXpect.Core.IThat subject) { } public static aweXpect.Results.AndOrResult> IsStatic(this aweXpect.Core.IThat subject) { } + public static aweXpect.Results.AndOrResult> IsVirtual(this aweXpect.Core.IThat subject) { } + public static aweXpect.Results.AndOrResult> Overrides(this aweXpect.Core.IThat subject) { } public sealed class EventOfTypeResult : aweXpect.Results.AndOrResult, aweXpect.Core.IOptionsProvider where TResult : aweXpect.Core.IThat { @@ -978,6 +986,8 @@ namespace aweXpect.Reflection public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> AreNotSealed(this aweXpect.Core.IThat> subject) { } public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> AreNotStatic(this aweXpect.Core.IThat> subject) { } public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> AreNotStatic(this aweXpect.Core.IThat> subject) { } + public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> AreNotVirtual(this aweXpect.Core.IThat> subject) { } + public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> AreNotVirtual(this aweXpect.Core.IThat> subject) { } public static aweXpect.Reflection.ThatEvents.EventsOfTypeResult, aweXpect.Core.IThat>> AreOfExactType(this aweXpect.Core.IThat> subject, System.Type handlerType) { } public static aweXpect.Reflection.ThatEvents.EventsOfTypeResult, aweXpect.Core.IThat>> AreOfExactType(this aweXpect.Core.IThat> subject, System.Type handlerType) { } public static aweXpect.Reflection.ThatEvents.EventsOfTypeResult, aweXpect.Core.IThat>> AreOfExactType(this aweXpect.Core.IThat> subject) { } @@ -990,10 +1000,14 @@ namespace aweXpect.Reflection public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> AreSealed(this aweXpect.Core.IThat> subject) { } public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> AreStatic(this aweXpect.Core.IThat> subject) { } public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> AreStatic(this aweXpect.Core.IThat> subject) { } + public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> AreVirtual(this aweXpect.Core.IThat> subject) { } + public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> AreVirtual(this aweXpect.Core.IThat> subject) { } public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> DoNotHave(this aweXpect.Core.IThat> subject, bool inherit = true) where TAttribute : System.Attribute { } public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> DoNotHave(this aweXpect.Core.IThat> subject, bool inherit = true) where TAttribute : System.Attribute { } + public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> DoNotOverride(this aweXpect.Core.IThat> subject) { } + public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> DoNotOverride(this aweXpect.Core.IThat> subject) { } public static aweXpect.Reflection.Results.HaveAttributeResult> Have(this aweXpect.Core.IThat> subject, bool inherit = true) where TAttribute : System.Attribute { } public static aweXpect.Reflection.Results.HaveAttributeResult> Have(this aweXpect.Core.IThat> subject, bool inherit = true) @@ -1002,6 +1016,8 @@ namespace aweXpect.Reflection where TAttribute : System.Attribute { } public static aweXpect.Reflection.Results.HaveAttributeResult> Have(this aweXpect.Core.IThat> subject, System.Func predicate, bool inherit = true, [System.Runtime.CompilerServices.CallerArgumentExpression("predicate")] string doNotPopulateThisValue = "") where TAttribute : System.Attribute { } + public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> Override(this aweXpect.Core.IThat> subject) { } + public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> Override(this aweXpect.Core.IThat> subject) { } public sealed class EventsOfTypeResult : aweXpect.Results.AndOrResult, aweXpect.Core.IOptionsProvider where TResult : aweXpect.Core.IThat { diff --git a/Tests/aweXpect.Reflection.Api.Tests/Expected/aweXpect.Reflection_netstandard2.0.txt b/Tests/aweXpect.Reflection.Api.Tests/Expected/aweXpect.Reflection_netstandard2.0.txt index 02829e2e..bd112053 100644 --- a/Tests/aweXpect.Reflection.Api.Tests/Expected/aweXpect.Reflection_netstandard2.0.txt +++ b/Tests/aweXpect.Reflection.Api.Tests/Expected/aweXpect.Reflection_netstandard2.0.txt @@ -229,6 +229,7 @@ namespace aweXpect.Reflection public static aweXpect.Reflection.Collections.Filtered.Events WhichAreNotPublic(this aweXpect.Reflection.Collections.Filtered.Events @this) { } public static aweXpect.Reflection.Collections.Filtered.Events WhichAreNotSealed(this aweXpect.Reflection.Collections.Filtered.Events @this) { } public static aweXpect.Reflection.Collections.Filtered.Events WhichAreNotStatic(this aweXpect.Reflection.Collections.Filtered.Events @this) { } + public static aweXpect.Reflection.Collections.Filtered.Events WhichAreNotVirtual(this aweXpect.Reflection.Collections.Filtered.Events @this) { } public static aweXpect.Reflection.Collections.Filtered.Events WhichAreObsolete(this aweXpect.Reflection.Collections.Filtered.Events @this) { } public static aweXpect.Reflection.Collections.Filtered.Events WhichArePrivate(this aweXpect.Reflection.Collections.Filtered.Events @this) { } public static aweXpect.Reflection.Collections.Filtered.Events WhichArePrivateProtected(this aweXpect.Reflection.Collections.Filtered.Events @this) { } @@ -237,6 +238,9 @@ namespace aweXpect.Reflection public static aweXpect.Reflection.Collections.Filtered.Events WhichArePublic(this aweXpect.Reflection.Collections.Filtered.Events @this) { } public static aweXpect.Reflection.Collections.Filtered.Events WhichAreSealed(this aweXpect.Reflection.Collections.Filtered.Events @this) { } public static aweXpect.Reflection.Collections.Filtered.Events WhichAreStatic(this aweXpect.Reflection.Collections.Filtered.Events @this) { } + public static aweXpect.Reflection.Collections.Filtered.Events WhichAreVirtual(this aweXpect.Reflection.Collections.Filtered.Events @this) { } + public static aweXpect.Reflection.Collections.Filtered.Events WhichDoNotOverride(this aweXpect.Reflection.Collections.Filtered.Events @this) { } + public static aweXpect.Reflection.Collections.Filtered.Events WhichOverride(this aweXpect.Reflection.Collections.Filtered.Events @this) { } public static aweXpect.Reflection.EventFilters.EventsWith With(this aweXpect.Reflection.Collections.Filtered.Events @this, bool inherit = true) where TAttribute : System.Attribute { } public static aweXpect.Reflection.EventFilters.EventsWith With(this aweXpect.Reflection.Collections.Filtered.Events @this, System.Func? predicate, bool inherit = true, [System.Runtime.CompilerServices.CallerArgumentExpression("predicate")] string doNotPopulateThisValue = "") @@ -858,6 +862,7 @@ namespace aweXpect.Reflection { public static aweXpect.Results.AndOrResult> DoesNotHave(this aweXpect.Core.IThat subject, bool inherit = true) where TAttribute : System.Attribute { } + public static aweXpect.Results.AndOrResult> DoesNotOverride(this aweXpect.Core.IThat subject) { } public static aweXpect.Reflection.Results.HasAttributeResult Has(this aweXpect.Core.IThat subject, bool inherit = true) where TAttribute : System.Attribute { } public static aweXpect.Reflection.Results.HasAttributeResult Has(this aweXpect.Core.IThat subject, System.Func predicate, bool inherit = true, [System.Runtime.CompilerServices.CallerArgumentExpression("predicate")] string doNotPopulateThisValue = "") @@ -866,12 +871,15 @@ namespace aweXpect.Reflection public static aweXpect.Results.AndOrResult> IsNotAbstract(this aweXpect.Core.IThat subject) { } public static aweXpect.Results.AndOrResult> IsNotSealed(this aweXpect.Core.IThat subject) { } public static aweXpect.Results.AndOrResult> IsNotStatic(this aweXpect.Core.IThat subject) { } + public static aweXpect.Results.AndOrResult> IsNotVirtual(this aweXpect.Core.IThat subject) { } public static aweXpect.Reflection.ThatEvent.EventOfTypeResult> IsOfExactType(this aweXpect.Core.IThat subject, System.Type handlerType) { } public static aweXpect.Reflection.ThatEvent.EventOfTypeResult> IsOfExactType(this aweXpect.Core.IThat subject) { } public static aweXpect.Reflection.ThatEvent.EventOfTypeResult> IsOfType(this aweXpect.Core.IThat subject, System.Type handlerType) { } public static aweXpect.Reflection.ThatEvent.EventOfTypeResult> IsOfType(this aweXpect.Core.IThat subject) { } public static aweXpect.Results.AndOrResult> IsSealed(this aweXpect.Core.IThat subject) { } public static aweXpect.Results.AndOrResult> IsStatic(this aweXpect.Core.IThat subject) { } + public static aweXpect.Results.AndOrResult> IsVirtual(this aweXpect.Core.IThat subject) { } + public static aweXpect.Results.AndOrResult> Overrides(this aweXpect.Core.IThat subject) { } public sealed class EventOfTypeResult : aweXpect.Results.AndOrResult, aweXpect.Core.IOptionsProvider where TResult : aweXpect.Core.IThat { @@ -888,18 +896,22 @@ namespace aweXpect.Reflection public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> AreNotAbstract(this aweXpect.Core.IThat> subject) { } public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> AreNotSealed(this aweXpect.Core.IThat> subject) { } public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> AreNotStatic(this aweXpect.Core.IThat> subject) { } + public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> AreNotVirtual(this aweXpect.Core.IThat> subject) { } public static aweXpect.Reflection.ThatEvents.EventsOfTypeResult, aweXpect.Core.IThat>> AreOfExactType(this aweXpect.Core.IThat> subject, System.Type handlerType) { } public static aweXpect.Reflection.ThatEvents.EventsOfTypeResult, aweXpect.Core.IThat>> AreOfExactType(this aweXpect.Core.IThat> subject) { } public static aweXpect.Reflection.ThatEvents.EventsOfTypeResult, aweXpect.Core.IThat>> AreOfType(this aweXpect.Core.IThat> subject, System.Type handlerType) { } public static aweXpect.Reflection.ThatEvents.EventsOfTypeResult, aweXpect.Core.IThat>> AreOfType(this aweXpect.Core.IThat> subject) { } public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> AreSealed(this aweXpect.Core.IThat> subject) { } public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> AreStatic(this aweXpect.Core.IThat> subject) { } + public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> AreVirtual(this aweXpect.Core.IThat> subject) { } public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> DoNotHave(this aweXpect.Core.IThat> subject, bool inherit = true) where TAttribute : System.Attribute { } + public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> DoNotOverride(this aweXpect.Core.IThat> subject) { } public static aweXpect.Reflection.Results.HaveAttributeResult> Have(this aweXpect.Core.IThat> subject, bool inherit = true) where TAttribute : System.Attribute { } public static aweXpect.Reflection.Results.HaveAttributeResult> Have(this aweXpect.Core.IThat> subject, System.Func predicate, bool inherit = true, [System.Runtime.CompilerServices.CallerArgumentExpression("predicate")] string doNotPopulateThisValue = "") where TAttribute : System.Attribute { } + public static aweXpect.Results.AndOrResult, aweXpect.Core.IThat>> Override(this aweXpect.Core.IThat> subject) { } public sealed class EventsOfTypeResult : aweXpect.Results.AndOrResult, aweXpect.Core.IOptionsProvider where TResult : aweXpect.Core.IThat { diff --git a/Tests/aweXpect.Reflection.Internal.Tests/Helpers/EventInfoHelpersTests.cs b/Tests/aweXpect.Reflection.Internal.Tests/Helpers/EventInfoHelpersTests.cs index 344d91f9..c2fddff9 100644 --- a/Tests/aweXpect.Reflection.Internal.Tests/Helpers/EventInfoHelpersTests.cs +++ b/Tests/aweXpect.Reflection.Internal.Tests/Helpers/EventInfoHelpersTests.cs @@ -72,6 +72,99 @@ public async Task HasAttribute_WithPredicate_ShouldReturnPredicateResult() await That(result2).IsFalse(); } + [Fact] + public async Task IsOverride_WhenAddMethodIsNull_ShouldReturnFalse() + { + EventInfo eventInfo = new EventInfoWithoutAddMethod(); + + bool result = eventInfo.IsOverride(); + + await That(result).IsFalse(); + } + + [Fact] + public async Task IsOverride_WhenEventInfoIsNull_ShouldReturnFalse() + { + EventInfo? eventInfo = null; + + bool result = eventInfo.IsOverride(); + + await That(result).IsFalse(); + } + + [Theory] + [InlineData(nameof(DerivedEventClass.AbstractEvent), true)] + [InlineData(nameof(DerivedEventClass.VirtualEvent), true)] + [InlineData(nameof(DerivedEventClass.DerivedPlainEvent), false)] + public async Task IsOverride_WhenEventIsDeclaredOnDerivedClass_ShouldReturnExpectedResult( + string eventName, bool expectedResult) + { + EventInfo eventInfo = typeof(DerivedEventClass).GetEvent(eventName)!; + + bool result = eventInfo.IsOverride(); + + await That(result).IsEqualTo(expectedResult); + } + + [Theory] + [InlineData(nameof(BaseEventClass.AbstractEvent))] + [InlineData(nameof(BaseEventClass.VirtualEvent))] + public async Task IsOverride_WhenEventIsDeclaredOnBaseClass_ShouldReturnFalse(string eventName) + { + EventInfo eventInfo = typeof(BaseEventClass).GetEvent(eventName)!; + + bool result = eventInfo.IsOverride(); + + await That(result).IsFalse(); + } + + [Fact] + public async Task IsReallyVirtual_WhenAddMethodIsNull_ShouldReturnFalse() + { + EventInfo eventInfo = new EventInfoWithoutAddMethod(); + + bool result = eventInfo.IsReallyVirtual(); + + await That(result).IsFalse(); + } + + [Fact] + public async Task IsReallyVirtual_WhenEventInfoIsNull_ShouldReturnFalse() + { + EventInfo? eventInfo = null; + + bool result = eventInfo.IsReallyVirtual(); + + await That(result).IsFalse(); + } + + [Theory] + [InlineData(nameof(BaseEventClass.AbstractEvent), true)] + [InlineData(nameof(BaseEventClass.VirtualEvent), true)] + [InlineData(nameof(BaseEventClass.PlainEvent), false)] + [InlineData(nameof(BaseEventClass.StaticEvent), false)] + public async Task IsReallyVirtual_WhenEventIsDeclaredOnBaseClass_ShouldReturnExpectedResult( + string eventName, bool expectedResult) + { + EventInfo eventInfo = typeof(BaseEventClass).GetEvent(eventName)!; + + bool result = eventInfo.IsReallyVirtual(); + + await That(result).IsEqualTo(expectedResult); + } + + [Theory] + [InlineData(nameof(DerivedEventClass.AbstractEvent))] + [InlineData(nameof(DerivedEventClass.VirtualEvent))] + public async Task IsReallyVirtual_WhenEventIsDeclaredOnDerivedClass_ShouldReturnTrue(string eventName) + { + EventInfo eventInfo = typeof(DerivedEventClass).GetEvent(eventName)!; + + bool result = eventInfo.IsReallyVirtual(); + + await That(result).IsTrue(); + } + [AttributeUsage(AttributeTargets.Event)] private class DummyAttribute : Attribute { @@ -99,6 +192,41 @@ private class TestClassBase { [Dummy(1)] public virtual event Dummy EventWithAttributeInBaseClass; } + + private abstract class BaseEventClass + { + public abstract event Dummy AbstractEvent; + public virtual event Dummy VirtualEvent; + public event Dummy PlainEvent; + public static event Dummy StaticEvent; + } + + private class DerivedEventClass : BaseEventClass + { + public override event Dummy AbstractEvent; + public sealed override event Dummy VirtualEvent; + public event Dummy DerivedPlainEvent; + } + + private sealed class EventInfoWithoutAddMethod : EventInfo + { + public override EventAttributes Attributes => EventAttributes.None; + public override Type? DeclaringType => typeof(EventInfoHelpersTests); + public override string Name => nameof(EventInfoWithoutAddMethod); + public override Type? ReflectedType => typeof(EventInfoHelpersTests); + + public override MethodInfo? GetAddMethod(bool nonPublic) => null; + + public override object[] GetCustomAttributes(bool inherit) => []; + + public override object[] GetCustomAttributes(Type attributeType, bool inherit) => []; + + public override MethodInfo? GetRaiseMethod(bool nonPublic) => null; + + public override MethodInfo? GetRemoveMethod(bool nonPublic) => null; + + public override bool IsDefined(Type attributeType, bool inherit) => false; + } #pragma warning restore CS0067 #pragma warning restore CS8618 } diff --git a/Tests/aweXpect.Reflection.Tests/Filters/EventFilters.WhichAreNotVirtual.Tests.cs b/Tests/aweXpect.Reflection.Tests/Filters/EventFilters.WhichAreNotVirtual.Tests.cs new file mode 100644 index 00000000..59e26076 --- /dev/null +++ b/Tests/aweXpect.Reflection.Tests/Filters/EventFilters.WhichAreNotVirtual.Tests.cs @@ -0,0 +1,23 @@ +using aweXpect.Reflection.Collections; + +namespace aweXpect.Reflection.Tests.Filters; + +public sealed partial class EventFilters +{ + public sealed class WhichAreNotVirtual + { + public sealed class Tests + { + [Fact] + public async Task ShouldAllowFilteringForNonVirtualEvents() + { + Filtered.Events events = In.AssemblyContaining() + .Types().Events().WhichAreNotVirtual(); + + await That(events).All().Satisfy(x => x.AddMethod?.IsVirtual != true).And.IsNotEmpty(); + await That(events.GetDescription()) + .IsEqualTo("non-virtual events in types in assembly").AsPrefix(); + } + } + } +} diff --git a/Tests/aweXpect.Reflection.Tests/Filters/EventFilters.WhichAreVirtual.Tests.cs b/Tests/aweXpect.Reflection.Tests/Filters/EventFilters.WhichAreVirtual.Tests.cs new file mode 100644 index 00000000..9aeba4ff --- /dev/null +++ b/Tests/aweXpect.Reflection.Tests/Filters/EventFilters.WhichAreVirtual.Tests.cs @@ -0,0 +1,23 @@ +using aweXpect.Reflection.Collections; + +namespace aweXpect.Reflection.Tests.Filters; + +public sealed partial class EventFilters +{ + public sealed class WhichAreVirtual + { + public sealed class Tests + { + [Fact] + public async Task ShouldAllowFilteringForVirtualEvents() + { + Filtered.Events events = In.AssemblyContaining() + .Types().Events().WhichAreVirtual(); + + await That(events).All().Satisfy(x => x.AddMethod?.IsVirtual == true).And.IsNotEmpty(); + await That(events.GetDescription()) + .IsEqualTo("virtual events in types in assembly").AsPrefix(); + } + } + } +} diff --git a/Tests/aweXpect.Reflection.Tests/Filters/EventFilters.WhichDoNotOverride.Tests.cs b/Tests/aweXpect.Reflection.Tests/Filters/EventFilters.WhichDoNotOverride.Tests.cs new file mode 100644 index 00000000..e3b006a6 --- /dev/null +++ b/Tests/aweXpect.Reflection.Tests/Filters/EventFilters.WhichDoNotOverride.Tests.cs @@ -0,0 +1,25 @@ +using aweXpect.Reflection.Collections; + +namespace aweXpect.Reflection.Tests.Filters; + +public sealed partial class EventFilters +{ + public sealed class WhichDoNotOverride + { + public sealed class Tests + { + [Fact] + public async Task ShouldAllowFilteringForNonOverridingEvents() + { + Filtered.Events events = In.AssemblyContaining() + .Types().Events().WhichDoNotOverride(); + + await That(events) + .All().Satisfy(x => x.AddMethod?.GetBaseDefinition().DeclaringType == x.AddMethod?.DeclaringType) + .And.IsNotEmpty(); + await That(events.GetDescription()) + .IsEqualTo("events which do not override a base event in types in assembly").AsPrefix(); + } + } + } +} diff --git a/Tests/aweXpect.Reflection.Tests/Filters/EventFilters.WhichOverride.Tests.cs b/Tests/aweXpect.Reflection.Tests/Filters/EventFilters.WhichOverride.Tests.cs new file mode 100644 index 00000000..27e3ed44 --- /dev/null +++ b/Tests/aweXpect.Reflection.Tests/Filters/EventFilters.WhichOverride.Tests.cs @@ -0,0 +1,25 @@ +using aweXpect.Reflection.Collections; + +namespace aweXpect.Reflection.Tests.Filters; + +public sealed partial class EventFilters +{ + public sealed class WhichOverride + { + public sealed class Tests + { + [Fact] + public async Task ShouldAllowFilteringForOverridingEvents() + { + Filtered.Events events = In.AssemblyContaining() + .Types().Events().WhichOverride(); + + await That(events) + .All().Satisfy(x => x.AddMethod?.GetBaseDefinition().DeclaringType != x.AddMethod?.DeclaringType) + .And.IsNotEmpty(); + await That(events.GetDescription()) + .IsEqualTo("events which override a base event in types in assembly").AsPrefix(); + } + } + } +} diff --git a/Tests/aweXpect.Reflection.Tests/ThatEvent.DoesNotOverride.Tests.cs b/Tests/aweXpect.Reflection.Tests/ThatEvent.DoesNotOverride.Tests.cs new file mode 100644 index 00000000..3f760819 --- /dev/null +++ b/Tests/aweXpect.Reflection.Tests/ThatEvent.DoesNotOverride.Tests.cs @@ -0,0 +1,101 @@ +using System.Reflection; +using aweXpect.Reflection.Tests.TestHelpers.Types; +using Xunit.Sdk; + +namespace aweXpect.Reflection.Tests; + +public sealed partial class ThatEvent +{ + public sealed class DoesNotOverride + { + public sealed class Tests + { + [Fact] + public async Task WhenEventDoesNotOverride_ShouldSucceed() + { + EventInfo subject = + typeof(AbstractClassWithMembers).GetEvent(nameof(AbstractClassWithMembers.VirtualEvent))!; + + async Task Act() + { + await That(subject).DoesNotOverride(); + } + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenEventIsNull_ShouldFail() + { + EventInfo? subject = null; + + async Task Act() + { + await That(subject).DoesNotOverride(); + } + + await That(Act).ThrowsException() + .WithMessage(""" + Expected that subject + does not override a base event, + but it was + """); + } + + [Fact] + public async Task WhenEventOverrides_ShouldFail() + { + EventInfo subject = + typeof(ClassWithSealedMembers).GetEvent(nameof(ClassWithSealedMembers.VirtualEvent))!; + + async Task Act() + { + await That(subject).DoesNotOverride(); + } + + await That(Act).ThrowsException() + .WithMessage($""" + Expected that subject + does not override a base event, + but it did override a base event {Formatter.Format(subject)} + """); + } + } + + public sealed class NegatedTests + { + [Fact] + public async Task WhenEventDoesNotOverride_ShouldFail() + { + EventInfo subject = + typeof(AbstractClassWithMembers).GetEvent(nameof(AbstractClassWithMembers.VirtualEvent))!; + + async Task Act() + { + await That(subject).DoesNotComplyWith(it => it.DoesNotOverride()); + } + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + overrides a base event, + but it did not override a base event event EventHandler AbstractClassWithMembers.VirtualEvent + """); + } + + [Fact] + public async Task WhenEventOverrides_ShouldSucceed() + { + EventInfo subject = + typeof(ClassWithSealedMembers).GetEvent(nameof(ClassWithSealedMembers.VirtualEvent))!; + + async Task Act() + { + await That(subject).DoesNotComplyWith(it => it.DoesNotOverride()); + } + + await That(Act).DoesNotThrow(); + } + } + } +} diff --git a/Tests/aweXpect.Reflection.Tests/ThatEvent.IsNotVirtual.Tests.cs b/Tests/aweXpect.Reflection.Tests/ThatEvent.IsNotVirtual.Tests.cs new file mode 100644 index 00000000..8a4dce3e --- /dev/null +++ b/Tests/aweXpect.Reflection.Tests/ThatEvent.IsNotVirtual.Tests.cs @@ -0,0 +1,101 @@ +using System.Reflection; +using aweXpect.Reflection.Tests.TestHelpers.Types; +using Xunit.Sdk; + +namespace aweXpect.Reflection.Tests; + +public sealed partial class ThatEvent +{ + public sealed class IsNotVirtual + { + public sealed class Tests + { + [Fact] + public async Task WhenEventIsNotVirtual_ShouldSucceed() + { + EventInfo subject = + typeof(BaseClassWithMembers).GetEvent(nameof(BaseClassWithMembers.BaseEvent))!; + + async Task Act() + { + await That(subject).IsNotVirtual(); + } + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenEventIsNull_ShouldFail() + { + EventInfo? subject = null; + + async Task Act() + { + await That(subject).IsNotVirtual(); + } + + await That(Act).ThrowsException() + .WithMessage(""" + Expected that subject + is not virtual, + but it was + """); + } + + [Fact] + public async Task WhenEventIsVirtual_ShouldFail() + { + EventInfo subject = + typeof(AbstractClassWithMembers).GetEvent(nameof(AbstractClassWithMembers.VirtualEvent))!; + + async Task Act() + { + await That(subject).IsNotVirtual(); + } + + await That(Act).ThrowsException() + .WithMessage($""" + Expected that subject + is not virtual, + but it was virtual {Formatter.Format(subject)} + """); + } + } + + public sealed class NegatedTests + { + [Fact] + public async Task WhenEventIsNotVirtual_ShouldFail() + { + EventInfo subject = + typeof(BaseClassWithMembers).GetEvent(nameof(BaseClassWithMembers.BaseEvent))!; + + async Task Act() + { + await That(subject).DoesNotComplyWith(it => it.IsNotVirtual()); + } + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + is virtual, + but it was non-virtual event EventHandler BaseClassWithMembers.BaseEvent + """); + } + + [Fact] + public async Task WhenEventIsVirtual_ShouldSucceed() + { + EventInfo subject = + typeof(AbstractClassWithMembers).GetEvent(nameof(AbstractClassWithMembers.VirtualEvent))!; + + async Task Act() + { + await That(subject).DoesNotComplyWith(it => it.IsNotVirtual()); + } + + await That(Act).DoesNotThrow(); + } + } + } +} diff --git a/Tests/aweXpect.Reflection.Tests/ThatEvent.IsVirtual.Tests.cs b/Tests/aweXpect.Reflection.Tests/ThatEvent.IsVirtual.Tests.cs new file mode 100644 index 00000000..8756d79d --- /dev/null +++ b/Tests/aweXpect.Reflection.Tests/ThatEvent.IsVirtual.Tests.cs @@ -0,0 +1,101 @@ +using System.Reflection; +using aweXpect.Reflection.Tests.TestHelpers.Types; +using Xunit.Sdk; + +namespace aweXpect.Reflection.Tests; + +public sealed partial class ThatEvent +{ + public sealed class IsVirtual + { + public sealed class Tests + { + [Fact] + public async Task WhenEventIsNotVirtual_ShouldFail() + { + EventInfo subject = + typeof(BaseClassWithMembers).GetEvent(nameof(BaseClassWithMembers.BaseEvent))!; + + async Task Act() + { + await That(subject).IsVirtual(); + } + + await That(Act).ThrowsException() + .WithMessage($""" + Expected that subject + is virtual, + but it was non-virtual {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenEventIsNull_ShouldFail() + { + EventInfo? subject = null; + + async Task Act() + { + await That(subject).IsVirtual(); + } + + await That(Act).ThrowsException() + .WithMessage(""" + Expected that subject + is virtual, + but it was + """); + } + + [Fact] + public async Task WhenEventIsVirtual_ShouldSucceed() + { + EventInfo subject = + typeof(AbstractClassWithMembers).GetEvent(nameof(AbstractClassWithMembers.VirtualEvent))!; + + async Task Act() + { + await That(subject).IsVirtual(); + } + + await That(Act).DoesNotThrow(); + } + } + + public sealed class NegatedTests + { + [Fact] + public async Task WhenEventIsNotVirtual_ShouldSucceed() + { + EventInfo subject = + typeof(BaseClassWithMembers).GetEvent(nameof(BaseClassWithMembers.BaseEvent))!; + + async Task Act() + { + await That(subject).DoesNotComplyWith(it => it.IsVirtual()); + } + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenEventIsVirtual_ShouldFail() + { + EventInfo subject = + typeof(AbstractClassWithMembers).GetEvent(nameof(AbstractClassWithMembers.VirtualEvent))!; + + async Task Act() + { + await That(subject).DoesNotComplyWith(it => it.IsVirtual()); + } + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + is not virtual, + but it was virtual event EventHandler AbstractClassWithMembers.VirtualEvent + """); + } + } + } +} diff --git a/Tests/aweXpect.Reflection.Tests/ThatEvent.Overrides.Tests.cs b/Tests/aweXpect.Reflection.Tests/ThatEvent.Overrides.Tests.cs new file mode 100644 index 00000000..fce209b1 --- /dev/null +++ b/Tests/aweXpect.Reflection.Tests/ThatEvent.Overrides.Tests.cs @@ -0,0 +1,101 @@ +using System.Reflection; +using aweXpect.Reflection.Tests.TestHelpers.Types; +using Xunit.Sdk; + +namespace aweXpect.Reflection.Tests; + +public sealed partial class ThatEvent +{ + public sealed class Overrides + { + public sealed class Tests + { + [Fact] + public async Task WhenEventDoesNotOverride_ShouldFail() + { + EventInfo subject = + typeof(AbstractClassWithMembers).GetEvent(nameof(AbstractClassWithMembers.VirtualEvent))!; + + async Task Act() + { + await That(subject).Overrides(); + } + + await That(Act).ThrowsException() + .WithMessage($""" + Expected that subject + overrides a base event, + but it did not override a base event {Formatter.Format(subject)} + """); + } + + [Fact] + public async Task WhenEventIsNull_ShouldFail() + { + EventInfo? subject = null; + + async Task Act() + { + await That(subject).Overrides(); + } + + await That(Act).ThrowsException() + .WithMessage(""" + Expected that subject + overrides a base event, + but it was + """); + } + + [Fact] + public async Task WhenEventOverrides_ShouldSucceed() + { + EventInfo subject = + typeof(ClassWithSealedMembers).GetEvent(nameof(ClassWithSealedMembers.VirtualEvent))!; + + async Task Act() + { + await That(subject).Overrides(); + } + + await That(Act).DoesNotThrow(); + } + } + + public sealed class NegatedTests + { + [Fact] + public async Task WhenEventDoesNotOverride_ShouldSucceed() + { + EventInfo subject = + typeof(AbstractClassWithMembers).GetEvent(nameof(AbstractClassWithMembers.VirtualEvent))!; + + async Task Act() + { + await That(subject).DoesNotComplyWith(it => it.Overrides()); + } + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenEventOverrides_ShouldFail() + { + EventInfo subject = + typeof(ClassWithSealedMembers).GetEvent(nameof(ClassWithSealedMembers.VirtualEvent))!; + + async Task Act() + { + await That(subject).DoesNotComplyWith(it => it.Overrides()); + } + + await That(Act).Throws() + .WithMessage(""" + Expected that subject + does not override a base event, + but it did override a base event event EventHandler ClassWithSealedMembers.VirtualEvent + """); + } + } + } +} diff --git a/Tests/aweXpect.Reflection.Tests/ThatEvents.AreNotVirtual.Tests.cs b/Tests/aweXpect.Reflection.Tests/ThatEvents.AreNotVirtual.Tests.cs new file mode 100644 index 00000000..44f1bdf8 --- /dev/null +++ b/Tests/aweXpect.Reflection.Tests/ThatEvents.AreNotVirtual.Tests.cs @@ -0,0 +1,132 @@ +using System.Collections.Generic; +using System.Reflection; +using aweXpect.Reflection.Tests.TestHelpers.Types; +#if NET8_0_OR_GREATER +using aweXpect.Reflection.Tests.TestHelpers; +#endif + +namespace aweXpect.Reflection.Tests; + +public sealed partial class ThatEvents +{ + public sealed class AreNotVirtual + { + public sealed class Tests + { + [Fact] + public async Task WhenEventsContainVirtualEvents_ShouldFail() + { + IEnumerable subject = typeof(AbstractClassWithMembers) + .GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); + + async Task Act() + { + await That(subject).AreNotVirtual(); + } + + await That(Act).ThrowsException() + .WithMessage(""" + Expected that subject + are all not virtual, + but it contained virtual events [ + * + ] + """).AsWildcard(); + } + + [Fact] + public async Task WhenFilteringOnlyNonVirtualEvents_ShouldSucceed() + { + IEnumerable subject = typeof(BaseClassWithMembers) + .GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); + + async Task Act() + { + await That(subject).AreNotVirtual(); + } + + await That(Act).DoesNotThrow(); + } + } + + public sealed class NegatedTests + { + [Fact] + public async Task WhenEventsContainVirtualEvents_ShouldSucceed() + { + IEnumerable subject = typeof(AbstractClassWithMembers) + .GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); + + async Task Act() + { + await That(subject).DoesNotComplyWith(they => they.AreNotVirtual()); + } + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenFilteringOnlyNonVirtualEvents_ShouldFail() + { + IEnumerable subject = typeof(BaseClassWithMembers) + .GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); + + async Task Act() + { + await That(subject).DoesNotComplyWith(they => they.AreNotVirtual()); + } + + await That(Act).ThrowsException() + .WithMessage(""" + Expected that subject + also contain a virtual event, + but it only contained non-virtual events [ + * + ] + """).AsWildcard(); + } + } + +#if NET8_0_OR_GREATER + public sealed class AsyncEnumerableTests + { + [Fact] + public async Task WhenEventsContainVirtualEvents_ShouldFail() + { + IAsyncEnumerable subject = typeof(AbstractClassWithMembers) + .GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly) + .ToTestAsyncEnumerable(); + + async Task Act() + { + await That(subject).AreNotVirtual(); + } + + await That(Act).ThrowsException() + .WithMessage(""" + Expected that subject + are all not virtual, + but it contained virtual events [ + * + ] + """).AsWildcard(); + } + + [Fact] + public async Task WhenFilteringOnlyNonVirtualEvents_ShouldSucceed() + { + IAsyncEnumerable subject = typeof(BaseClassWithMembers) + .GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly) + .ToTestAsyncEnumerable(); + + async Task Act() + { + await That(subject).AreNotVirtual(); + } + + await That(Act).DoesNotThrow(); + } + } +#endif + } +} diff --git a/Tests/aweXpect.Reflection.Tests/ThatEvents.AreVirtual.Tests.cs b/Tests/aweXpect.Reflection.Tests/ThatEvents.AreVirtual.Tests.cs new file mode 100644 index 00000000..ecd0f32f --- /dev/null +++ b/Tests/aweXpect.Reflection.Tests/ThatEvents.AreVirtual.Tests.cs @@ -0,0 +1,132 @@ +using System.Collections.Generic; +using System.Reflection; +using aweXpect.Reflection.Tests.TestHelpers.Types; +#if NET8_0_OR_GREATER +using aweXpect.Reflection.Tests.TestHelpers; +#endif + +namespace aweXpect.Reflection.Tests; + +public sealed partial class ThatEvents +{ + public sealed class AreVirtual + { + public sealed class Tests + { + [Fact] + public async Task WhenEventsContainNonVirtualEvents_ShouldFail() + { + IEnumerable subject = typeof(BaseClassWithMembers) + .GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); + + async Task Act() + { + await That(subject).AreVirtual(); + } + + await That(Act).ThrowsException() + .WithMessage(""" + Expected that subject + are all virtual, + but it contained non-virtual events [ + * + ] + """).AsWildcard(); + } + + [Fact] + public async Task WhenFilteringOnlyVirtualEvents_ShouldSucceed() + { + IEnumerable subject = typeof(AbstractClassWithMembers) + .GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); + + async Task Act() + { + await That(subject).AreVirtual(); + } + + await That(Act).DoesNotThrow(); + } + } + + public sealed class NegatedTests + { + [Fact] + public async Task WhenEventsContainNonVirtualEvents_ShouldSucceed() + { + IEnumerable subject = typeof(BaseClassWithMembers) + .GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); + + async Task Act() + { + await That(subject).DoesNotComplyWith(they => they.AreVirtual()); + } + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenFilteringOnlyVirtualEvents_ShouldFail() + { + IEnumerable subject = typeof(AbstractClassWithMembers) + .GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); + + async Task Act() + { + await That(subject).DoesNotComplyWith(they => they.AreVirtual()); + } + + await That(Act).ThrowsException() + .WithMessage(""" + Expected that subject + are not all virtual, + but it only contained virtual events [ + * + ] + """).AsWildcard(); + } + } + +#if NET8_0_OR_GREATER + public sealed class AsyncEnumerableTests + { + [Fact] + public async Task WhenEventsContainNonVirtualEvents_ShouldFail() + { + IAsyncEnumerable subject = typeof(BaseClassWithMembers) + .GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly) + .ToTestAsyncEnumerable(); + + async Task Act() + { + await That(subject).AreVirtual(); + } + + await That(Act).ThrowsException() + .WithMessage(""" + Expected that subject + are all virtual, + but it contained non-virtual events [ + * + ] + """).AsWildcard(); + } + + [Fact] + public async Task WhenFilteringOnlyVirtualEvents_ShouldSucceed() + { + IAsyncEnumerable subject = typeof(AbstractClassWithMembers) + .GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly) + .ToTestAsyncEnumerable(); + + async Task Act() + { + await That(subject).AreVirtual(); + } + + await That(Act).DoesNotThrow(); + } + } +#endif + } +} diff --git a/Tests/aweXpect.Reflection.Tests/ThatEvents.DoNotOverride.Tests.cs b/Tests/aweXpect.Reflection.Tests/ThatEvents.DoNotOverride.Tests.cs new file mode 100644 index 00000000..4284999e --- /dev/null +++ b/Tests/aweXpect.Reflection.Tests/ThatEvents.DoNotOverride.Tests.cs @@ -0,0 +1,132 @@ +using System.Collections.Generic; +using System.Reflection; +using aweXpect.Reflection.Tests.TestHelpers.Types; +#if NET8_0_OR_GREATER +using aweXpect.Reflection.Tests.TestHelpers; +#endif + +namespace aweXpect.Reflection.Tests; + +public sealed partial class ThatEvents +{ + public sealed class DoNotOverride + { + public sealed class Tests + { + [Fact] + public async Task WhenEventsContainOverridingEvents_ShouldFail() + { + IEnumerable subject = typeof(ClassWithSealedMembers) + .GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); + + async Task Act() + { + await That(subject).DoNotOverride(); + } + + await That(Act).ThrowsException() + .WithMessage(""" + Expected that subject + all do not override a base event, + but it contained events which override a base event [ + * + ] + """).AsWildcard(); + } + + [Fact] + public async Task WhenFilteringOnlyNonOverridingEvents_ShouldSucceed() + { + IEnumerable subject = typeof(AbstractClassWithMembers) + .GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); + + async Task Act() + { + await That(subject).DoNotOverride(); + } + + await That(Act).DoesNotThrow(); + } + } + + public sealed class NegatedTests + { + [Fact] + public async Task WhenEventsContainOverridingEvents_ShouldSucceed() + { + IEnumerable subject = typeof(ClassWithSealedMembers) + .GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); + + async Task Act() + { + await That(subject).DoesNotComplyWith(they => they.DoNotOverride()); + } + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenFilteringOnlyNonOverridingEvents_ShouldFail() + { + IEnumerable subject = typeof(AbstractClassWithMembers) + .GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); + + async Task Act() + { + await That(subject).DoesNotComplyWith(they => they.DoNotOverride()); + } + + await That(Act).ThrowsException() + .WithMessage(""" + Expected that subject + also contain an event which overrides a base event, + but it only contained events which do not override a base event [ + * + ] + """).AsWildcard(); + } + } + +#if NET8_0_OR_GREATER + public sealed class AsyncEnumerableTests + { + [Fact] + public async Task WhenEventsContainOverridingEvents_ShouldFail() + { + IAsyncEnumerable subject = typeof(ClassWithSealedMembers) + .GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly) + .ToTestAsyncEnumerable(); + + async Task Act() + { + await That(subject).DoNotOverride(); + } + + await That(Act).ThrowsException() + .WithMessage(""" + Expected that subject + all do not override a base event, + but it contained events which override a base event [ + * + ] + """).AsWildcard(); + } + + [Fact] + public async Task WhenFilteringOnlyNonOverridingEvents_ShouldSucceed() + { + IAsyncEnumerable subject = typeof(AbstractClassWithMembers) + .GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly) + .ToTestAsyncEnumerable(); + + async Task Act() + { + await That(subject).DoNotOverride(); + } + + await That(Act).DoesNotThrow(); + } + } +#endif + } +} diff --git a/Tests/aweXpect.Reflection.Tests/ThatEvents.Override.Tests.cs b/Tests/aweXpect.Reflection.Tests/ThatEvents.Override.Tests.cs new file mode 100644 index 00000000..6678b9ea --- /dev/null +++ b/Tests/aweXpect.Reflection.Tests/ThatEvents.Override.Tests.cs @@ -0,0 +1,132 @@ +using System.Collections.Generic; +using System.Reflection; +using aweXpect.Reflection.Tests.TestHelpers.Types; +#if NET8_0_OR_GREATER +using aweXpect.Reflection.Tests.TestHelpers; +#endif + +namespace aweXpect.Reflection.Tests; + +public sealed partial class ThatEvents +{ + public sealed class Override + { + public sealed class Tests + { + [Fact] + public async Task WhenEventsContainNonOverridingEvents_ShouldFail() + { + IEnumerable subject = typeof(AbstractClassWithMembers) + .GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); + + async Task Act() + { + await That(subject).Override(); + } + + await That(Act).ThrowsException() + .WithMessage(""" + Expected that subject + all override a base event, + but it contained events which do not override a base event [ + * + ] + """).AsWildcard(); + } + + [Fact] + public async Task WhenFilteringOnlyOverridingEvents_ShouldSucceed() + { + IEnumerable subject = typeof(ClassWithSealedMembers) + .GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); + + async Task Act() + { + await That(subject).Override(); + } + + await That(Act).DoesNotThrow(); + } + } + + public sealed class NegatedTests + { + [Fact] + public async Task WhenEventsContainNonOverridingEvents_ShouldSucceed() + { + IEnumerable subject = typeof(AbstractClassWithMembers) + .GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); + + async Task Act() + { + await That(subject).DoesNotComplyWith(they => they.Override()); + } + + await That(Act).DoesNotThrow(); + } + + [Fact] + public async Task WhenFilteringOnlyOverridingEvents_ShouldFail() + { + IEnumerable subject = typeof(ClassWithSealedMembers) + .GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); + + async Task Act() + { + await That(subject).DoesNotComplyWith(they => they.Override()); + } + + await That(Act).ThrowsException() + .WithMessage(""" + Expected that subject + do not all override a base event, + but it only contained events which override a base event [ + * + ] + """).AsWildcard(); + } + } + +#if NET8_0_OR_GREATER + public sealed class AsyncEnumerableTests + { + [Fact] + public async Task WhenEventsContainNonOverridingEvents_ShouldFail() + { + IAsyncEnumerable subject = typeof(AbstractClassWithMembers) + .GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly) + .ToTestAsyncEnumerable(); + + async Task Act() + { + await That(subject).Override(); + } + + await That(Act).ThrowsException() + .WithMessage(""" + Expected that subject + all override a base event, + but it contained events which do not override a base event [ + * + ] + """).AsWildcard(); + } + + [Fact] + public async Task WhenFilteringOnlyOverridingEvents_ShouldSucceed() + { + IAsyncEnumerable subject = typeof(ClassWithSealedMembers) + .GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly) + .ToTestAsyncEnumerable(); + + async Task Act() + { + await That(subject).Override(); + } + + await That(Act).DoesNotThrow(); + } + } +#endif + } +}