Skip to content

Commit 99122ee

Browse files
committed
Address second round of PR review comments: guard unsupported types in GetCustomAttributesCached, add null-guard test, fix integration test attribute ordering, add doc comments
1 parent 26610d1 commit 99122ee

4 files changed

Lines changed: 31 additions & 4 deletions

File tree

src/Adapter/MSTestAdapter.PlatformServices/Services/ReflectionOperations.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,13 @@ public IEnumerable<TAttributeType> GetAttributes<TAttributeType>(ICustomAttribut
224224
/// <returns>attributes defined.</returns>
225225
public Attribute[] GetCustomAttributesCached(ICustomAttributeProvider attributeProvider)
226226
{
227+
if (attributeProvider is not (MemberInfo or Assembly))
228+
{
229+
throw new ArgumentException(
230+
$"Unsupported attribute provider type: {attributeProvider?.GetType()}. Only MemberInfo and Assembly are supported.",
231+
nameof(attributeProvider));
232+
}
233+
227234
// If the information is cached, then use it otherwise populate the cache using
228235
// the reflection APIs.
229236
return _attributeCache.GetOrAdd(attributeProvider, GetAttributes);

test/IntegrationTests/PlatformServices.Desktop.IntegrationTests/ReflectionUtilityTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public void GetCustomAttributesShouldReturnAllAttributes()
4545
attributes.Should().NotBeNull();
4646
attributes.Should().HaveCount(2);
4747

48-
string[] expectedAttributes = ["TestCategory : base", "Owner : base"];
48+
string[] expectedAttributes = ["Owner : base", "TestCategory : base"];
4949
GetAttributeValuePairs(attributes!).Should().Equal(expectedAttributes);
5050
}
5151

@@ -59,7 +59,7 @@ public void GetCustomAttributesShouldReturnAllAttributesWithBaseInheritance()
5959
attributes.Should().HaveCount(3);
6060

6161
// Notice that the Owner on the base method does not show up since it can only be defined once.
62-
string[] expectedAttributes = ["TestCategory : derived", "TestCategory : base", "Owner : derived"];
62+
string[] expectedAttributes = ["Owner : derived", "TestCategory : derived", "TestCategory : base"];
6363
GetAttributeValuePairs(attributes!).Should().Equal(expectedAttributes);
6464
}
6565

@@ -125,7 +125,7 @@ public void GetCustomAttributesShouldReturnAllAttributesIncludingUserDefinedAttr
125125
attributes.Should().NotBeNull();
126126
attributes.Should().HaveCount(3);
127127

128-
string[] expectedAttributes = ["Duration : superfast", "TestCategory : base", "Owner : base"];
128+
string[] expectedAttributes = ["Duration : superfast", "Owner : base", "TestCategory : base"];
129129
GetAttributeValuePairs(attributes!).Should().Equal(expectedAttributes);
130130
}
131131

test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/Services/ReflectionOperationsTests.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ public class ReflectionOperationsTests : TestContainer
2222
private readonly Mock<MethodInfo> _method;
2323
private readonly TestablePlatformServiceProvider _testablePlatformServiceProvider;
2424

25+
// NOTE: This class mutates the shared static PlatformServiceProvider.Instance (set in
26+
// the constructor, restored in Dispose). Tests that call GetCustomAttributesCached or
27+
// methods that go through NotCachedReflectionAccessor depend on this static being set
28+
// to _testablePlatformServiceProvider. This pattern is inherited from the former
29+
// ReflectHelperTests. If parallel execution with other test classes that also mutate
30+
// PlatformServiceProvider.Instance causes intermittent failures, consider adding
31+
// [DoNotParallelize] to this class.
2532
public ReflectionOperationsTests()
2633
{
2734
_reflectionOperations = new ReflectionOperations();
@@ -235,6 +242,13 @@ public void IsAttributeDefinedShouldReturnTrueIfSpecifiedAttributeIsDefinedOnAMe
235242
rh.IsAttributeDefined<TestMethodAttribute>(mockMemberInfo.Object).Should().BeTrue();
236243
}
237244

245+
public void IsAttributeDefinedShouldThrowWhenMemberInfoIsNull()
246+
{
247+
var rh = new ReflectionOperations();
248+
Action action = () => rh.IsAttributeDefined<TestMethodAttribute>(null!);
249+
action.Should().Throw<ArgumentNullException>().WithParameterName("memberInfo");
250+
}
251+
238252
public void IsAttributeDefinedShouldReturnFalseIfSpecifiedAttributeIsNotDefinedOnAMember()
239253
{
240254
var rh = new ReflectionOperations();
@@ -439,6 +453,12 @@ internal class AttributeMockingHelper
439453
private readonly List<(Type Type, Attribute Attribute, MemberTypes MemberType)> _data = [];
440454
private readonly Mock<IReflectionOperations> _mockReflectionOperations;
441455

456+
/// <summary>
457+
/// Adds (not replaces) attribute entries of <paramref name="memberTypes"/>
458+
/// to the internal list used by the mock handler. Successive calls for the
459+
/// same <paramref name="memberTypes"/> are cumulative — previous entries are
460+
/// kept alongside new ones.
461+
/// </summary>
442462
public void SetCustomAttribute(Type type, Attribute[] values, MemberTypes memberTypes)
443463
{
444464
foreach (Attribute attribute in values)

test/UnitTests/MSTestAdapter.PlatformServices.UnitTests/TestableImplementations/MockableReflectionOperations.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public Attribute[] GetCustomAttributesCached(ICustomAttributeProvider attributeP
7575
{
7676
MemberInfo memberInfo => mock.Object.GetCustomAttributes(memberInfo)?.OfType<Attribute>().ToArray() ?? [],
7777
Assembly assembly => mock.Object.GetCustomAttributes(assembly, typeof(Attribute))?.OfType<Attribute>().ToArray() ?? [],
78-
_ => attributeProvider.GetCustomAttributes(true).OfType<Attribute>().ToArray(),
78+
_ => throw new NotSupportedException($"Unsupported attribute provider type: {attributeProvider.GetType()}. Only MemberInfo and Assembly are supported."),
7979
};
8080

8181
public bool IsMethodDeclaredInSameAssemblyAsType(MethodInfo method, Type type)

0 commit comments

Comments
 (0)