2

I'm currently mocking out an Interface with NSubstitute, which is basically a representation of a class with two properties and one method.

LoginViewModel = Substitute.For<ILoginViewModel>();

The mocked out interface is instantiated, then passed into a method which reflects upon it to get all the custom attributes.

LoginViewModel.Username = "User1";
LoginViewModel.Password = "Password1";

Each of the properties on the concrete implementation of the interface has a single custom attribute, however when reflected, the compiler shows no custom attributes.

[CustomRequired]
public string Username { get; set; }

[CustomRequired]
public string Password { get; set; }

Testing this without NSubstitute works. My question is: Does NSubstitute strip out Custom Attributes? Or is there a way to allow them through?

TheGeekZn
  • 3,696
  • 10
  • 55
  • 91

1 Answers1

1

I don't know too much about custom attributes, so it is worth double checking the information in my answer.

First, NSubstitute does strip out some specific attributes, but not attributes in general. (Aside: NSubstitute uses Castle DynamicProxy to generate the proxy types, so to be more accurate NSubstitute asks Castle DP to strip these out. :) )

Secondly, if the attributes are declared on an interface they will not flow on to the class. They will however be available via the interface type itself. They will also be available if declared on a class and on substitutes for that class (provided the attribute is not configured explicitly to prevent being inherited):

public class MyAttribute : Attribute { }
public interface IHaveAttributes {
    [My] string Sample { get; set; }
}
public class HaveAttributes : IHaveAttributes {
    [My] public virtual string Sample { get; set; }
}
public class NoAttributes : IHaveAttributes {
    public virtual string Sample { get; set; }
}

[Test]
public void TestAttributes()
{
    // WORKS for class:
    var sub = Substitute.For<HaveAttributes>();
    var sampleProp = sub.GetType().GetProperty("Sample");
    var attributes = Attribute.GetCustomAttributes(sampleProp, typeof(MyAttribute));
    Assert.AreEqual(1, attributes.Length);

    // WORKS directly from interface:
    var sampleInterfaceProp = typeof(IHaveAttributes).GetProperty("Sample");
    var attributes2 = Attribute.GetCustomAttributes(sampleInterfaceProp, typeof(MyAttribute));
    Assert.AreEqual(1, attributes2.Length);

    // Does NOT go from interface through to class (even non-substitutes):
    var no = new NoAttributes();
    var sampleProp2 = no.GetType().GetProperty("Sample");
    var noAttributes = Attribute.GetCustomAttributes(sampleProp2, typeof(MyAttribute));
    Assert.IsEmpty(noAttributes);
}
Community
  • 1
  • 1
David Tchepak
  • 9,826
  • 2
  • 56
  • 68
  • Thanks for the reply - I've added the custom attributes on both the Interface and the Class, however there are still no attributes. Here is a screenshot of the reflected type: http://i.imgur.com/xjPKLqF.png – TheGeekZn Jun 14 '16 at 09:47
  • The screenshot shows it is still looking at declaring type `ILoginViewModelProxy`. You'll have substitute for the class (`LoginViewModel`?) if you want the members to have those attributes. – David Tchepak Jun 14 '16 at 11:06
  • Ahh makes sense! Thanks so much - Working now :) – TheGeekZn Jun 14 '16 at 12:44