Repository: dotnet/aspnetcore
File: src/Mvc/Mvc.Core/test/ModelBinding/Metadata/ModelAttributesTest.cs (C#)

Code before:
        Assert.Equal(2, attributes.PropertyAttributes.Count);
        Assert.IsType<RequiredAttribute>(attributes.PropertyAttributes[0]);
        Assert.IsType<RangeAttribute>(attributes.PropertyAttributes[1]);

        var attribute = Assert.Single(attributes.TypeAttributes);
        Assert.IsType<ClassValidator>(attribute);
    }

    [Fact]
    public void GetAttributesForParameter_NoAttributes()
    {
        // Arrange & Act
        var attributes = ModelAttributes.GetAttributesForParameter(
            typeof(MethodWithParamAttributesType)
                .GetMethod(nameof(MethodWithParamAttributesType.Method))
                .GetParameters()[0]);

        // Assert
        // Not exactly "no attributes" due to pseudo-attributes on object.
        // After CoreCLR consistency fix, object.GetCustomAttributes() returns all pseudo-attributes.
        Assert.Equal(5, attributes.Attributes.Count);
        Assert.Contains(attributes.Attributes, attr => attr is SerializableAttribute);
        Assert.Contains(attributes.Attributes, attr => attr.GetType().Name == "NullableContextAttribute");
        Assert.Contains(attributes.Attributes, attr => attr.GetType().Name == "ClassInterfaceAttribute");
        Assert.Contains(attributes.Attributes, attr => attr.GetType().Name == "ComVisibleAttribute");
        Assert.Contains(attributes.Attributes, attr => attr.GetType().Name == "TypeForwardedFromAttribute");
        Assert.Empty(attributes.ParameterAttributes);
        Assert.Null(attributes.PropertyAttributes);
        Assert.Equal(attributes.Attributes, attributes.TypeAttributes);
    }

    [Fact]
    public void GetAttributesForParameter_SomeAttributes()
    {
        // Arrange & Act
        var attributes = ModelAttributes.GetAttributesForParameter(
            typeof(MethodWithParamAttributesType)
                .GetMethod(nameof(MethodWithParamAttributesType.Method))
                .GetParameters()[1]);

        // Assert
        Assert.Collection(
            // Take(2) to ignore ComVisibleAttribute, SerializableAttribute, ... on int.
            attributes.Attributes.Take(2),
            attribute => Assert.IsType<RequiredAttribute>(attribute),
            attribute => Assert.IsType<RangeAttribute>(attribute));
        Assert.Collection(
            attributes.ParameterAttributes,
            attribute => Assert.IsType<RequiredAttribute>(attribute),
            attribute => Assert.IsType<RangeAttribute>(attribute));
        Assert.Null(attributes.PropertyAttributes);

Review comment (suggestion):
Using string comparison with GetType().Name for attribute type checking is fragile and could break if the attribute type is renamed or moved to a different namespace. Consider using typeof() comparison or checking if the attribute is assignable from the expected type.
```suggestion
        Assert.Contains(attributes.Attributes, attr => attr.GetType() == Type.GetType("System.Runtime.CompilerServices.NullableContextAttribute"));
        Assert.Contains(attributes.Attributes, attr => attr.GetType() == typeof(System.Runtime.InteropServices.ClassInterfaceAttribute));
        Assert.Contains(attributes.Attributes, attr => attr.GetType() == typeof(System.Runtime.InteropServices.ComVisibleAttribute));
        Assert.Contains(attributes.Attributes, attr => attr.GetType() == typeof(System.Runtime.Serialization.TypeForwardedFromAttribute));
```

Code after:
        Assert.Equal(2, attributes.PropertyAttributes.Count);
        Assert.IsType<RequiredAttribute>(attributes.PropertyAttributes[0]);
        Assert.IsType<RangeAttribute>(attributes.PropertyAttributes[1]);

        var attribute = Assert.Single(attributes.TypeAttributes);
        Assert.IsType<ClassValidator>(attribute);
    }

    [Fact]
    public void GetAttributesForParameter_NoAttributes()
    {
        // Arrange & Act
        var attributes = ModelAttributes.GetAttributesForParameter(
            typeof(MethodWithParamAttributesType)
                .GetMethod(nameof(MethodWithParamAttributesType.Method))
                .GetParameters()[0]);

        // Assert
        // The parameter itself has no attributes
        Assert.Empty(attributes.ParameterAttributes);
        Assert.Null(attributes.PropertyAttributes);

        // Type attributes exist (but we don't care what they are - that's runtime implementation detail)
        Assert.NotEmpty(attributes.TypeAttributes);

        // Combined attributes = ParameterAttributes + TypeAttributes (when parameter has no attributes)
        Assert.Equal(attributes.TypeAttributes, attributes.Attributes);
    }

    [Fact]
    public void GetAttributesForParameter_SomeAttributes()
    {
        // Arrange & Act
        var attributes = ModelAttributes.GetAttributesForParameter(
            typeof(MethodWithParamAttributesType)
                .GetMethod(nameof(MethodWithParamAttributesType.Method))
                .GetParameters()[1]);

        // Assert
        Assert.Collection(
            // Take(2) to ignore ComVisibleAttribute, SerializableAttribute, ... on int.
            attributes.Attributes.Take(2),
            attribute => Assert.IsType<RequiredAttribute>(attribute),
            attribute => Assert.IsType<RangeAttribute>(attribute));
        Assert.Collection(
            attributes.ParameterAttributes,
            attribute => Assert.IsType<RequiredAttribute>(attribute),
            attribute => Assert.IsType<RangeAttribute>(attribute));
        Assert.Null(attributes.PropertyAttributes);
        Assert.Collection(
            // Take(1) because the attribute or attributes after SerializableAttribute are framework-specific.