|
3 | 3 | using System; |
4 | 4 | using System.Collections.Generic; |
5 | 5 | using System.Linq; |
| 6 | + using System.Reflection; |
6 | 7 |
|
7 | 8 | using FluentAssertions; |
8 | 9 |
|
|
18 | 19 | [Trait("Category", "Attributes")] |
19 | 20 | public class CustomizeWithAttributeTests |
20 | 21 | { |
| 22 | + public static IEnumerable<object[]> ArgumentsDiscoveryCustomizationTestData { get; } = new[] |
| 23 | + { |
| 24 | + new object[] { false, null, 0 }, |
| 25 | + new object[] { false, Array.Empty<object>(), 0 }, |
| 26 | + new object[] { false, new object[] { bool.TrueString }, 1 }, |
| 27 | + new object[] { true, null, 1 }, |
| 28 | + new object[] { true, Array.Empty<object>(), 1 }, |
| 29 | + new object[] { true, new object[] { bool.TrueString }, 2 }, |
| 30 | + }; |
| 31 | + |
21 | 32 | [Fact(DisplayName = "GIVEN customization type with no arguments WHEN GetCustomization is invoked THEN customization instance is returned")] |
22 | 33 | public void GivenCustomizationTypeWithNoArguments_WhenGetCustomizationIsInvoked_ThenCustomizationInstanceIsReturned() |
23 | 34 | { |
@@ -92,6 +103,45 @@ public void GivenUnsupportedType_WhenConstructorIsInvoked_ThenExceptionIsThrown( |
92 | 103 | Assert.Throws<ArgumentException>(() => new CustomizeWithAttribute(customizationType)); |
93 | 104 | } |
94 | 105 |
|
| 106 | + [Fact(DisplayName = "GIVEN CustomizeWith attribute with IncludeParameterType set WHEN GetCustomization is invoked THEN customization with expected type is returned")] |
| 107 | + public void GivenCustomizeWithAttributeWithIncludeParameterTypeSet_WhenGetCustomizationIsInvoked_ThenCustomizationWithExpectedTypeIsReturned() |
| 108 | + { |
| 109 | + // Arrange |
| 110 | + var customizationType = typeof(ArgumentsDiscoveryCustomization); |
| 111 | + var customizeAttribute = new CustomizeWithAttribute(customizationType) { IncludeParameterType = true }; |
| 112 | + var parameter = typeof(CustomizeWithAttributeTests) |
| 113 | + .GetMethod(nameof(this.MethodUnderTest), BindingFlags.Instance | BindingFlags.NonPublic) |
| 114 | + .GetParameters() |
| 115 | + .First(); |
| 116 | + |
| 117 | + // Act |
| 118 | + var customization = customizeAttribute.GetCustomization(parameter) as ArgumentsDiscoveryCustomization; |
| 119 | + |
| 120 | + // Assert |
| 121 | + customization.Should().NotBeNull().And.BeAssignableTo(customizationType); |
| 122 | + customization.Args.Should().HaveCount(1).And.Subject.First().Should().Be(parameter.ParameterType); |
| 123 | + } |
| 124 | + |
| 125 | + [Theory(DisplayName = "GIVEN CustomizeWith attribute with arguments WHEN GetCustomization is invoked THEN expected customization is returned with expected numner of arguments")] |
| 126 | + [MemberData(nameof(ArgumentsDiscoveryCustomizationTestData))] |
| 127 | + public void GivenCustomizeWithAttributeWithArguments_WhenGetCustomizationIsInvoked_ThenExpectedCustomizationIsReturnedWithExpectedNumnerOfArguments(bool includeParameterType, object[] args, int expectedNumberOfArguments) |
| 128 | + { |
| 129 | + // Arrange |
| 130 | + var customizationType = typeof(ArgumentsDiscoveryCustomization); |
| 131 | + var customizeAttribute = new CustomizeWithAttribute(customizationType, args) { IncludeParameterType = includeParameterType }; |
| 132 | + var parameter = typeof(CustomizeWithAttributeTests) |
| 133 | + .GetMethod(nameof(this.MethodUnderTest), BindingFlags.Instance | BindingFlags.NonPublic) |
| 134 | + .GetParameters() |
| 135 | + .First(); |
| 136 | + |
| 137 | + // Act |
| 138 | + var customization = customizeAttribute.GetCustomization(parameter) as ArgumentsDiscoveryCustomization; |
| 139 | + |
| 140 | + // Assert |
| 141 | + customization.Should().NotBeNull().And.BeAssignableTo(customizationType); |
| 142 | + customization.Args.Should().HaveCount(expectedNumberOfArguments); |
| 143 | + } |
| 144 | + |
95 | 145 | [Theory(DisplayName = "GIVEN CustomizeWith applied to the second argument WHEN data populated THEN only second one has customization")] |
96 | 146 | [AutoData] |
97 | 147 | public void GivenCustomizeWithAppliedToTheSecondArgument_WhenDataPopulated_ThenOnlySecondOneHasCustomization( |
@@ -131,6 +181,13 @@ public void GivenCustomizeWithAppliedToTheFirstArgumentOfACecrtainType_WhenDataP |
131 | 181 | instanceOfDifferentTypeWithoutCustomization.Should().NotBeEmpty(); |
132 | 182 | } |
133 | 183 |
|
| 184 | + [System.Diagnostics.CodeAnalysis.SuppressMessage("Roslynator", "RCS1163:Unused parameter.", Justification = "Required for test")] |
| 185 | + [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "Required for test")] |
| 186 | + protected void MethodUnderTest(bool parameter) |
| 187 | + { |
| 188 | + // Empty method under test |
| 189 | + } |
| 190 | + |
134 | 191 | protected sealed class EmptyCollectionAttribute : CustomizeWithAttribute<EmptyCollectionCustomization> |
135 | 192 | { |
136 | 193 | public EmptyCollectionAttribute() |
@@ -158,5 +215,20 @@ public void Customize(IFixture fixture) |
158 | 215 | new ExactTypeSpecification(this.ReflectedType))); |
159 | 216 | } |
160 | 217 | } |
| 218 | + |
| 219 | + protected class ArgumentsDiscoveryCustomization : ICustomization |
| 220 | + { |
| 221 | + public ArgumentsDiscoveryCustomization(params object[] args) |
| 222 | + { |
| 223 | + this.Args = args; |
| 224 | + } |
| 225 | + |
| 226 | + public IReadOnlyCollection<object> Args { get; } |
| 227 | + |
| 228 | + public void Customize(IFixture fixture) |
| 229 | + { |
| 230 | + // Method intentionally left empty. |
| 231 | + } |
| 232 | + } |
161 | 233 | } |
162 | 234 | } |
0 commit comments