From 2aa553a4ec77da3ccf11ed3f4f44e93cd13a7762 Mon Sep 17 00:00:00 2001 From: "uray.oernek" Date: Mon, 2 Jan 2023 09:52:05 +0100 Subject: [PATCH 01/12] Extended PropertyInfoSelector with GetSetMethod Added GetSetMethod Changed naming to better match the new functionality --- Src/FluentAssertions/Types/PropertyInfoSelector.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Src/FluentAssertions/Types/PropertyInfoSelector.cs b/Src/FluentAssertions/Types/PropertyInfoSelector.cs index 4c4f9ec6cb..98053fb108 100644 --- a/Src/FluentAssertions/Types/PropertyInfoSelector.cs +++ b/Src/FluentAssertions/Types/PropertyInfoSelector.cs @@ -48,8 +48,8 @@ public PropertyInfoSelector ThatArePublicOrInternal { selectedProperties = selectedProperties.Where(property => { - MethodInfo getter = property.GetGetMethod(nonPublic: true); - return (getter is not null) && (getter.IsPublic || getter.IsAssembly); + MethodInfo methodInfo = property.GetGetMethod(nonPublic: true) ?? property.GetSetMethod(nonPublic: true); + return (methodInfo is not null) && (methodInfo.IsPublic || methodInfo.IsAssembly); }); return this; From 73772b27ef6b780e862a6743ec6af1e89aa4bd31 Mon Sep 17 00:00:00 2001 From: "uray.oernek" Date: Mon, 2 Jan 2023 09:53:58 +0100 Subject: [PATCH 02/12] Added new tests for the PropertyInfoSelector Testing the new set accessor --- .../Types/PropertyInfoSelectorSpecs.cs | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/Tests/FluentAssertions.Specs/Types/PropertyInfoSelectorSpecs.cs b/Tests/FluentAssertions.Specs/Types/PropertyInfoSelectorSpecs.cs index b20b6535ff..d6e5f723a6 100644 --- a/Tests/FluentAssertions.Specs/Types/PropertyInfoSelectorSpecs.cs +++ b/Tests/FluentAssertions.Specs/Types/PropertyInfoSelectorSpecs.cs @@ -355,6 +355,32 @@ public void When_selecting_properties_return_types_it_should_return_the_correct_ , typeof(string), typeof(int), typeof(int), typeof(int), typeof(int) }); } + + [Fact] + public void When_selecting_propeties_with_only_set_accessors_it_should_return_the_applicable_properties() + { + // Arrange + Type type = typeof(TestClassForPropertyInfoSelector); + + // Act + IEnumerable properties = type.Properties().ThatArePublicOrInternal.ToArray(); + + // Assert + properties.Should().HaveCount(3); + } + + [Fact] + public void When_selecting_propeties_with_different_accessors_from_a_abstract_class_should_return_the_applicable_properties() + { + // Arrange + Type type = typeof(TestClassForPropertySelector); + + // Act + IEnumerable properties = type.Properties().ThatArePublicOrInternal.ToArray(); + + // Assert + properties.Should().HaveCount(8); + } } #region Internal classes used in unit tests @@ -456,4 +482,15 @@ public DummyPropertyAttribute(string value) public string Value { get; private set; } } +public class TestClassForPropertyInfoSelector +{ + private static string myPrivateStaticStringField; + + public static string PublicStaticStringProperty { set => myPrivateStaticStringField = value; } + + public static string InternalStaticStringProperty { get; set; } + + public int PublicIntProperty { init; get; } +} + #endregion From 0d63bf7ad31e384a77015b408bb9989aac835df6 Mon Sep 17 00:00:00 2001 From: "uray.oernek" Date: Mon, 2 Jan 2023 10:11:49 +0100 Subject: [PATCH 03/12] Adapted ThatArePublicOrInternal code documentation --- Src/FluentAssertions/Types/PropertyInfoSelector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Src/FluentAssertions/Types/PropertyInfoSelector.cs b/Src/FluentAssertions/Types/PropertyInfoSelector.cs index 98053fb108..f70193e4c1 100644 --- a/Src/FluentAssertions/Types/PropertyInfoSelector.cs +++ b/Src/FluentAssertions/Types/PropertyInfoSelector.cs @@ -40,7 +40,7 @@ public PropertyInfoSelector(IEnumerable types) } /// - /// Only select the properties that have a public or internal getter. + /// Only select the properties that have a public or internal getter and setter. /// public PropertyInfoSelector ThatArePublicOrInternal { From 6d709ab0ea1320850e7bd4fdaa1258153a925e4c Mon Sep 17 00:00:00 2001 From: "uray.oernek" Date: Mon, 2 Jan 2023 10:27:22 +0100 Subject: [PATCH 04/12] Add release notes --- docs/_pages/releases.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/_pages/releases.md b/docs/_pages/releases.md index 4230326b81..0e4c66ee2b 100644 --- a/docs/_pages/releases.md +++ b/docs/_pages/releases.md @@ -20,6 +20,7 @@ sidebar: * Added new extension methods to be able to write `Exactly.Times(n)`, `AtLeast.Times(n)` and `AtMost.Times(n)` in a more fluent way - [#2047](https://github.com/fluentassertions/fluentassertions/pull/2047) ### Fixes +* Fixed `ThatArePublicOrInternal` property of `PropertyInfoSelector` not including properties with set accessors - [#2084] (https://github.com/fluentassertions/fluentassertions/pull/2082) * Quering properties on classes, e.g. `typeof(MyClass).Properties()`, now also includes static properties - [#2054](https://github.com/fluentassertions/fluentassertions/pull/2054) * Nested AssertionScopes now print the inner scope reportables - [#2044](https://github.com/fluentassertions/fluentassertions/pull/2044) * Throw `ArgumentException` instead of `ArgumentNullException` when a required `string` argument is empty - [#2023](https://github.com/fluentassertions/fluentassertions/pull/2023) From 99fc98f007b91411c90445f8e21006f117c8744a Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 2 Jan 2023 12:03:40 +0100 Subject: [PATCH 05/12] Update Tests/FluentAssertions.Specs/Types/PropertyInfoSelectorSpecs.cs Co-authored-by: IT-VBFK <49762557+IT-VBFK@users.noreply.github.com> --- Tests/FluentAssertions.Specs/Types/PropertyInfoSelectorSpecs.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/FluentAssertions.Specs/Types/PropertyInfoSelectorSpecs.cs b/Tests/FluentAssertions.Specs/Types/PropertyInfoSelectorSpecs.cs index d6e5f723a6..29eabee3b3 100644 --- a/Tests/FluentAssertions.Specs/Types/PropertyInfoSelectorSpecs.cs +++ b/Tests/FluentAssertions.Specs/Types/PropertyInfoSelectorSpecs.cs @@ -370,7 +370,7 @@ public void When_selecting_propeties_with_only_set_accessors_it_should_return_th } [Fact] - public void When_selecting_propeties_with_different_accessors_from_a_abstract_class_should_return_the_applicable_properties() + public void When_selecting_propeties_with_different_accessors_from_an_abstract_class_should_return_the_applicable_properties() { // Arrange Type type = typeof(TestClassForPropertySelector); From 83f0643b59e866e6e7b06e6692e1df85c57ed6b3 Mon Sep 17 00:00:00 2001 From: "uray.oernek" Date: Mon, 2 Jan 2023 12:05:06 +0100 Subject: [PATCH 06/12] Fixed typo --- .../FluentAssertions.Specs/Types/PropertyInfoSelectorSpecs.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/FluentAssertions.Specs/Types/PropertyInfoSelectorSpecs.cs b/Tests/FluentAssertions.Specs/Types/PropertyInfoSelectorSpecs.cs index 29eabee3b3..ad539360ab 100644 --- a/Tests/FluentAssertions.Specs/Types/PropertyInfoSelectorSpecs.cs +++ b/Tests/FluentAssertions.Specs/Types/PropertyInfoSelectorSpecs.cs @@ -357,7 +357,7 @@ public void When_selecting_properties_return_types_it_should_return_the_correct_ } [Fact] - public void When_selecting_propeties_with_only_set_accessors_it_should_return_the_applicable_properties() + public void When_selecting_properties_with_only_set_accessors_it_should_return_the_applicable_properties() { // Arrange Type type = typeof(TestClassForPropertyInfoSelector); @@ -370,7 +370,7 @@ public void When_selecting_propeties_with_only_set_accessors_it_should_return_th } [Fact] - public void When_selecting_propeties_with_different_accessors_from_an_abstract_class_should_return_the_applicable_properties() + public void When_selecting_properties_with_different_accessors_from_an_abstract_class_should_return_the_applicable_properties() { // Arrange Type type = typeof(TestClassForPropertySelector); From 64c371f3867d82c1d2dc6e2c4b0825044556f2c0 Mon Sep 17 00:00:00 2001 From: "uray.oernek" Date: Mon, 2 Jan 2023 13:58:08 +0100 Subject: [PATCH 07/12] Adapted ThatArePublicOrInternal property implemenation --- Src/FluentAssertions/Types/PropertyInfoSelector.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Src/FluentAssertions/Types/PropertyInfoSelector.cs b/Src/FluentAssertions/Types/PropertyInfoSelector.cs index f70193e4c1..5f0d763b1d 100644 --- a/Src/FluentAssertions/Types/PropertyInfoSelector.cs +++ b/Src/FluentAssertions/Types/PropertyInfoSelector.cs @@ -40,7 +40,7 @@ public PropertyInfoSelector(IEnumerable types) } /// - /// Only select the properties that have a public or internal getter and setter. + /// Only select the properties that have atleast one public or internal accessor /// public PropertyInfoSelector ThatArePublicOrInternal { @@ -48,8 +48,8 @@ public PropertyInfoSelector ThatArePublicOrInternal { selectedProperties = selectedProperties.Where(property => { - MethodInfo methodInfo = property.GetGetMethod(nonPublic: true) ?? property.GetSetMethod(nonPublic: true); - return (methodInfo is not null) && (methodInfo.IsPublic || methodInfo.IsAssembly); + return property.GetGetMethod(nonPublic: true) is { IsPublic: true } or { IsAssembly: true } + || property.GetSetMethod(nonPublic: true) is { IsPublic: true } or { IsAssembly: true }; }); return this; From 5f86bece014ef55ac9313efe31fec17fb6b283ec Mon Sep 17 00:00:00 2001 From: "uray.oernek" Date: Mon, 2 Jan 2023 14:00:09 +0100 Subject: [PATCH 08/12] Added additional tests for private accessors --- .../Types/PropertyInfoSelectorSpecs.cs | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/Tests/FluentAssertions.Specs/Types/PropertyInfoSelectorSpecs.cs b/Tests/FluentAssertions.Specs/Types/PropertyInfoSelectorSpecs.cs index ad539360ab..d3c3268801 100644 --- a/Tests/FluentAssertions.Specs/Types/PropertyInfoSelectorSpecs.cs +++ b/Tests/FluentAssertions.Specs/Types/PropertyInfoSelectorSpecs.cs @@ -381,6 +381,19 @@ public void When_selecting_properties_with_different_accessors_from_an_abstract_ // Assert properties.Should().HaveCount(8); } + + [Fact] + public void When_selecting_properties_with_atleast_one_accessor_being_private_should_return_the_applicable_properties() + { + // Arrange + Type type = typeof(TestClassForPropertyInfoSelectorWithOnePrivateAccessor); + + // Act + IEnumerable properties = type.Properties().ThatArePublicOrInternal.ToArray(); + + // Assert + properties.Should().HaveCount(4); + } } #region Internal classes used in unit tests @@ -490,7 +503,18 @@ public class TestClassForPropertyInfoSelector public static string InternalStaticStringProperty { get; set; } - public int PublicIntProperty { init; get; } + public int PublicIntProperty { get; init; } +} + +public class TestClassForPropertyInfoSelectorWithOnePrivateAccessor +{ + public bool PublicBoolPrivateGet { private get; set; } + + public bool PublicBoolPrivateSet { get; private set; } + + internal bool InternalBoolPrivateGet { private get; set; } + + internal bool InternalBoolPrivateSet { get; private set; } } #endregion From a5494169d3773092e558cb48dd5586afbdecf64d Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 3 Jan 2023 10:33:15 +0100 Subject: [PATCH 09/12] Update docs/_pages/releases.md Co-authored-by: Jonas Nyrup --- docs/_pages/releases.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/_pages/releases.md b/docs/_pages/releases.md index 0e4c66ee2b..4dcfd2cef0 100644 --- a/docs/_pages/releases.md +++ b/docs/_pages/releases.md @@ -20,7 +20,7 @@ sidebar: * Added new extension methods to be able to write `Exactly.Times(n)`, `AtLeast.Times(n)` and `AtMost.Times(n)` in a more fluent way - [#2047](https://github.com/fluentassertions/fluentassertions/pull/2047) ### Fixes -* Fixed `ThatArePublicOrInternal` property of `PropertyInfoSelector` not including properties with set accessors - [#2084] (https://github.com/fluentassertions/fluentassertions/pull/2082) +* `PropertyInfoSelector.ThatArePublicOrInternal` now takes the setter into account when determining if a property is `public` or `internal` - [#2082] (https://github.com/fluentassertions/fluentassertions/pull/2082) * Quering properties on classes, e.g. `typeof(MyClass).Properties()`, now also includes static properties - [#2054](https://github.com/fluentassertions/fluentassertions/pull/2054) * Nested AssertionScopes now print the inner scope reportables - [#2044](https://github.com/fluentassertions/fluentassertions/pull/2044) * Throw `ArgumentException` instead of `ArgumentNullException` when a required `string` argument is empty - [#2023](https://github.com/fluentassertions/fluentassertions/pull/2023) From 6ef772e0b66f10655fdb657967a0720bb23573d6 Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 3 Jan 2023 10:33:27 +0100 Subject: [PATCH 10/12] Update Src/FluentAssertions/Types/PropertyInfoSelector.cs Co-authored-by: Jonas Nyrup --- Src/FluentAssertions/Types/PropertyInfoSelector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Src/FluentAssertions/Types/PropertyInfoSelector.cs b/Src/FluentAssertions/Types/PropertyInfoSelector.cs index 5f0d763b1d..1fb87c13be 100644 --- a/Src/FluentAssertions/Types/PropertyInfoSelector.cs +++ b/Src/FluentAssertions/Types/PropertyInfoSelector.cs @@ -40,7 +40,7 @@ public PropertyInfoSelector(IEnumerable types) } /// - /// Only select the properties that have atleast one public or internal accessor + /// Only select the properties that have at least one public or internal accessor /// public PropertyInfoSelector ThatArePublicOrInternal { From 6c1f1b621cb48dbdb9c9ed663c8d5d6fcc86e357 Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 3 Jan 2023 10:43:03 +0100 Subject: [PATCH 11/12] Update Tests/FluentAssertions.Specs/Types/PropertyInfoSelectorSpecs.cs Co-authored-by: Dennis Doomen --- Tests/FluentAssertions.Specs/Types/PropertyInfoSelectorSpecs.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/FluentAssertions.Specs/Types/PropertyInfoSelectorSpecs.cs b/Tests/FluentAssertions.Specs/Types/PropertyInfoSelectorSpecs.cs index d3c3268801..4f32899070 100644 --- a/Tests/FluentAssertions.Specs/Types/PropertyInfoSelectorSpecs.cs +++ b/Tests/FluentAssertions.Specs/Types/PropertyInfoSelectorSpecs.cs @@ -357,7 +357,7 @@ public void When_selecting_properties_return_types_it_should_return_the_correct_ } [Fact] - public void When_selecting_properties_with_only_set_accessors_it_should_return_the_applicable_properties() + public void When_a_property_only_has_a_public_setter_it_should_be_included_in_the_applicable_properties() { // Arrange Type type = typeof(TestClassForPropertyInfoSelector); From 7ad0054abfc99a60ff1f8edf08fc520953e1e0f0 Mon Sep 17 00:00:00 2001 From: "uray.oernek" Date: Mon, 9 Jan 2023 10:17:55 +0100 Subject: [PATCH 12/12] Restructured tests --- .../Types/PropertyInfoSelectorSpecs.cs | 126 ++++++++---------- 1 file changed, 57 insertions(+), 69 deletions(-) diff --git a/Tests/FluentAssertions.Specs/Types/PropertyInfoSelectorSpecs.cs b/Tests/FluentAssertions.Specs/Types/PropertyInfoSelectorSpecs.cs index 4f32899070..dd612bb0fd 100644 --- a/Tests/FluentAssertions.Specs/Types/PropertyInfoSelectorSpecs.cs +++ b/Tests/FluentAssertions.Specs/Types/PropertyInfoSelectorSpecs.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Reflection; using FluentAssertions.Types; using Internal.Main.Test; @@ -216,23 +215,6 @@ public void When_selecting_methods_that_do_not_return_a_specific_type_it_should_ properties.Should().HaveCount(4); } - [Fact] - public void When_combining_filters_to_filter_methods_it_should_return_only_the_applicable_methods() - { - // Arrange - Type type = typeof(TestClassForPropertySelector); - - // Act - IEnumerable properties = type.Properties() - .ThatArePublicOrInternal - .OfType() - .ThatAreDecoratedWith() - .ToArray(); - - // Assert - properties.Should().ContainSingle(); - } - [Fact] public void When_selecting_properties_decorated_with_an_inheritable_attribute_it_should_only_return_the_applicable_properties() { @@ -356,43 +338,72 @@ public void When_selecting_properties_return_types_it_should_return_the_correct_ }); } - [Fact] - public void When_a_property_only_has_a_public_setter_it_should_be_included_in_the_applicable_properties() + public class ThatArePublicOrInternal { - // Arrange - Type type = typeof(TestClassForPropertyInfoSelector); + [Fact] + public void When_combining_filters_to_filter_methods_it_should_return_only_the_applicable_methods() + { + // Arrange + Type type = typeof(TestClassForPropertySelector); - // Act - IEnumerable properties = type.Properties().ThatArePublicOrInternal.ToArray(); + // Act + IEnumerable properties = type.Properties() + .ThatArePublicOrInternal + .OfType() + .ThatAreDecoratedWith() + .ToArray(); - // Assert - properties.Should().HaveCount(3); - } + // Assert + properties.Should().ContainSingle(); + } - [Fact] - public void When_selecting_properties_with_different_accessors_from_an_abstract_class_should_return_the_applicable_properties() - { - // Arrange - Type type = typeof(TestClassForPropertySelector); + [Fact] + public void When_a_property_only_has_a_public_setter_it_should_be_included_in_the_applicable_properties() + { + // Arrange + Type type = typeof(TestClassForPublicSetter); - // Act - IEnumerable properties = type.Properties().ThatArePublicOrInternal.ToArray(); + // Act + IEnumerable properties = type.Properties().ThatArePublicOrInternal.ToArray(); - // Assert - properties.Should().HaveCount(8); - } + // Assert + properties.Should().HaveCount(3); + } - [Fact] - public void When_selecting_properties_with_atleast_one_accessor_being_private_should_return_the_applicable_properties() - { - // Arrange - Type type = typeof(TestClassForPropertyInfoSelectorWithOnePrivateAccessor); + private class TestClassForPublicSetter + { + private static string myPrivateStaticStringField; - // Act - IEnumerable properties = type.Properties().ThatArePublicOrInternal.ToArray(); + public static string PublicStaticStringProperty { set => myPrivateStaticStringField = value; } - // Assert - properties.Should().HaveCount(4); + public static string InternalStaticStringProperty { get; set; } + + public int PublicIntProperty { get; init; } + } + + [Fact] + public void When_selecting_properties_with_at_least_one_accessor_being_private_should_return_the_applicable_properties() + { + // Arrange + Type type = typeof(TestClassForPrivateAccessors); + + // Act + IEnumerable properties = type.Properties().ThatArePublicOrInternal.ToArray(); + + // Assert + properties.Should().HaveCount(4); + } + + private class TestClassForPrivateAccessors + { + public bool PublicBoolPrivateGet { private get; set; } + + public bool PublicBoolPrivateSet { get; private set; } + + internal bool InternalBoolPrivateGet { private get; set; } + + internal bool InternalBoolPrivateSet { get; private set; } + } } } @@ -494,27 +505,4 @@ public DummyPropertyAttribute(string value) public string Value { get; private set; } } - -public class TestClassForPropertyInfoSelector -{ - private static string myPrivateStaticStringField; - - public static string PublicStaticStringProperty { set => myPrivateStaticStringField = value; } - - public static string InternalStaticStringProperty { get; set; } - - public int PublicIntProperty { get; init; } -} - -public class TestClassForPropertyInfoSelectorWithOnePrivateAccessor -{ - public bool PublicBoolPrivateGet { private get; set; } - - public bool PublicBoolPrivateSet { get; private set; } - - internal bool InternalBoolPrivateGet { private get; set; } - - internal bool InternalBoolPrivateSet { get; private set; } -} - #endregion