c# - Throwing exceptions from attribute constructor - c#

I found this article on the subject and tried the following:
public class FailerAttr : Attribute {
public FailerAttr(string s) {
throw new Exception("I should definitely fail!");
}
}
And in unit test project I have the following:
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class Test {
[TestMethod]
public void GoFail() {
// Make sure attribute will get initialized
new Failer();
}
private class Failer {
[FailerAttr("")]
public int Prop { get; set; }
}
}
When I run the test, it succeeds. So, the questions are:
Why it does not fail?
Is it really a bad idea to throw exceptions from attributes? Because I think I need to.
Some environment info (just in case it's relevant):
Unit tests are run via ReSharper's unit test runner (R# v8.2.0.2160)
Visual studio v11.0.61030.0

Since attributes are part of class definition available to you at runtime (it's also called "metadata" in geekspeak) CLR does not instantiate them unless some part of your program asks for them. This makes sense: why bother spending CPU cycles for something that nobody wants to access?
Because of this, the execution of the constructor will never happen unless you ask for that attribute.
Here is one way to ask for an attribute that would make your program fail:
var attr = Attribute.GetCustomAttribute(typeof(Failer).GetProperty("Prop"), typeof(FailerAttr));
This code makes CLR instantiate the FailerAttr, which triggers the exception.
Demo on ideone.
If you do not know the type of the attribute, you can retrieve all attributes at once with this call:
var allAttributes = Attribute.GetCustomAttributes(typeof(Failer).GetProperty("Prop"));
This causes an exception as well (demo).

Attributes are not converted to executable code, they're converted to metadata.
Metadata like this is not used during normal execution, it is only if you start using the metadata, like through reflection, that the attribute type comes back into play.
The constructor or any of the code in the attribute is not executed during compilation. Instead the type and the parameters to the constructor is serialized into the metadata, and only upon inspection using reflection will the constructor actually be executed.
In other words, if you intend this to fail at compile time then you can't.
Try looking for the attributes using reflection, depending on the attribute object is deserialized from the metadata, the constructor may or may not be invoked, but it will definitely not be invoked by just applying it to identifiers.

Related

Nunit test gives result OneTimeSetUp: No suitable constructor was found

I have an issue where NUnit is telling me: "No suitable constructor was found". What causes this? I also get another message: "Exception doesn't have a stacktrace". Both messages just repeat over and over again. Here's my code
[TestFixture]
public class SecurityServiceTests
{
private IContext stubIContext;
private ISecurityService securityService;
private IWindsorContainer windsorContainer;
public SecurityServiceTests(IContext stubIContext)
{
this.stubIContext= stubIContext;
}
[TestFixtureSetUp]
public void TestSetup()
{
//Mocks the database context
stubIContext= MockRepository.GenerateStub<IContext>();
var returnedList = new List<string>();
stubIContext.Stub(a => a.GetUserSecurities(null)).IgnoreArguments().Return(returnedList);
securityService = new SecurityService(windsorContainer);
}
[Test]
public void ControllerShouldGetUserGroupForCurrentUsers()
{
//Act
var action = securityService.CurrentUserFeatureList;
//Assert
Assert.IsNotNull(action);
}
}
You are trying to create a parameterized fixture, so you have a constructor taking a single argument. Contrary to the comment above, this is valid in both NUnit V2 and V3.
However, in order for NUnit to use that constructor, you have to give it an argument to be applied and you have not done so. You would do this by specifying
[TestFixture(someArgument)]
Probably, you are intending to do something like that by assigning a value to stubIContext in the TestFixtureSetUp. However, that can't work for two reasons:
It's not being supplied to the constructor and that's where your fixture needs it.
Anyway, construction of the object takes place before that setup method is called.
There are several ways to get the stub created before the fixture is instantiated, particularly in NUnit v3. However, I don't actually see why you need this fixture to be parameterized, since you are using a stub anyway.
Unless you have some other need for parameterization, not shown in the example, I would simply create the stub in the setup. My preference would be to use SetUp rather than TestFixtureSetUp. Creating stubs is not expensive, so there seems to be no reason to economize. However, if there are reasons not seen in the excerpt, TestFixtureSetUp can work as well.
Your SecurityServiceTests class needs to have a default constructor to be used as a TextFixture.
From the docs on TextFixture:
There are a few restrictions on a class that is used as a test fixture.
It must be a publicly exported type or NUnit will not see it.
It must have a default constructor or NUnit will not be able to construct it.
It's not clear anyway why you have a constructor in that class that accepts and sets IContext stubIContext as you then go on to mock that field in the Setup.
Remove the public SecurityServiceTests(IContext stubIContext) constructor and the tests will run.
Edit: it's slightly different in NUnit3, as pointed out by #Chris in the comments:
If no arguments are provided with the TestFixtureAttribute, the class must have a default constructor.
If arguments are provided, they must match one of the constructors.
What I had, it's constructor was protected and not public,
so Nunit couldn't found it.

How to access a Static Class Private fields to unit test its methods using Microsoft Fakes in C#

I have the below static class and a method in it which I need to unit test. I am able to But this method has the if condition which uses a Boolean private variable and if the value of it is false then it executes the steps in that if condition.
public static class Logger
{
private static bool bNoError = true;
public static void Log()
{
if (!bNoError)
{
//Then execute the logic here
}
else
{
//else condition logic here
}
}
}
Is there a way I can set the private field bNoError value to true so that I can have one test method which tests the logic in if condition.
For UnitTesting purposes, Microsoft has implemented a few helper classes (PrivateType and PrivateObject) that use reflection for scenarios like this.
PrivateType myTypeAccessor = new PrivateType(typeof(TypeToAccess));
myTypeAccessor.SetStaticFieldOrProperty("bNoError", false);
PrivateType is intended for static access, whereas PrivateObject is for testing against instantiated objects instead.
You will need to include the Microsoft.VisualStudio.TestTools.UnitTesting namespace from the Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll in order to use these.
You can use Reflection to do that for testing purpose. Though it's quite outlaw.
using System.Reflection;
................
................
var field = typeof(Logger).GetField("bNoError",
BindingFlags.Static |
BindingFlags.NonPublic);
// Normally the first argument to "SetValue" is the instance
// of the type but since we are mutating a static field we pass "null"
field.SetValue(null, false);
Sometimes, you can get so close to the code you're trying to test that you forget to think of the big picture and start focusing in too much on the implementation. Rather than thinking "When XXX happens, ...", you start thinking "When this variable is set, ...". When you get to this point, it's a sign that you might be focusing too much on the implementation and you're running a significant risk of creating very brittle tests that will break if you change anything about your implementation.
#Martin Noreke's post covered how to do what you're trying to. It feels to me though, like you may be testing the wrong thing. It seems like the next test you are going to write, is "Do XXX with Logger and test that bNoError is set to false"
Obviously it depends a bit on the rest of the Logger class, but it feels like perhaps an alternate approach might be:
Call Logger method XXX, shimming dependencies if necessary in order to trigger error state.
Call Logger.Log and validate expected behaviour
Assuming there is a way for bNoError to get reset back to true, you could then:
Call Logger method YYY, shimming dependencies if necessary to trigger error cleanup
Call Logger.Log and validate expected behaviour
I don't recommend to use reflection on unit testing. It is difficult to maintain on large project with lot of developers, because it cannot be easily refactored, find.
Furthermore unit-test should test some behavior of class. If there is some kind of error handling in the tested class it should be accessible not only to unit-test but to the developer(invoker) in real scenario and not hidden by encapsulation. If I call some method in real scenario, I expect I can obtain error status or catch exception. Generally I prefer exception. Exception error handling can be tested easily by unit tested and no reflection to break encapsulation is needed.
So my suggestion is make it public:
public static class Logger
{
private bool bNoError = true;
public static void Log()
{
if (!bNoError)
{
//Then execute the logic here
}
else
{
//else condition logic here
}
}
public static bool IsAnyError()
{
return !bNoError;
}
}
Well, one way is to add a method to the original class and then shim it:
public static class Logger
{
// .... other stuff here
private static void SetbNoError(bool flag)
{
// leave implementation empty
}
}
Then in your test:
ShimLogger.SetbNoErrorBool = flag => bNoError = flag;

C#: Making sure parameter has attribute

I have an attribute lets call it SomeAttribute and a class i need to make sure the class is passed a type which has SomeAttribute. So this is how i do it now:
public class Test()
{
public Test(SomeType obj)
{
if(!obj.GetType().IsDefined(typeof(SomeAttribute), false))
{
throw new ArgumentException("Errormessage");
}
}
}
But this means that i don't get any errors at compile time but somewhere at runtime, if obj does not have the attribute. Is there a way to specify in the method declaration that the parameter must have some attribute ? So i get errors i compile time when using the wrong parameters, or do i have to use an empty interface ?
There's no way to enforce an attribute at compile-time. You may want to reconsider your design - usually attributes are more about metadata, less about runtime behavior.
NDepend's Code Query Language is a static anlysis tool that could probably detect violations - but if you're not already using NDepend, I'd be hesitant to include it for this requirement alone.
Then again, lacking context of what you want to do - it's a bit like solving the other half your problem.
No, there's no way of requiring an attribute - but you could always write unit tests to scan through your assemblies and check that the appropriate attributes had been applied - assuming you can actually detect this requirement.
It sounds somewhat odd though - could you give some more details as to why you're using this scheme? Perhaps another approach would be more appropriate, such as another parameter to describe the extra data you're interested in.

Testing un-compilable code in NUnit

I have a class which for now should always have a certain member populated before it is valid. To enforce this, the class has no default constructor and instead has a constructor which accepts a value for that required member. The setup is similar to this below:
public class MyClass
{
public string Owner { get; protected set; }
public MyClass(string owner)
{
this.Owner = owner;
}
}
Now I'd like to write a test to ensure that there is in fact no default constructor, so that if one gets added in the future, we are reminded of the reasons behind not having one and are forced to consider the impact of doing so. Although, obviously attempting to call the default constructor in a test won't just fail, it won't compile.
Is there a good way to pull off this kind of test without modifying my original class? If not, I suppose I could implement a default constructor which throws an exception. My only hesitation there is that calling the default constructor now becomes compilable code and then we must rely on other tests to ensure such code doesn't get written.
Thoughts?
You could call Activator.CreateInstance(typeof(MyClass)) to try to run the default constructor, and assert that a MissingMethodException is thrown.
[Test]
[ExpectedException(typeof(MissingMethodException))
public void ShouldBeNoDefaultConstructorForMyClass()
{
Activator.CreateInstance(typeof(MyClass));
}
I would create a default constructor, mark it private and put your documentation there. Then your reasons for doing it won't be hidden off somewhere. You have to realize you'll be giving up some serialization functionality that requires the parameterless constructor.
ConstructorInfo ci = typeof(MyClass).GetConstructor(Type.EmptyTypes);
Assert.IsNull(ci);
Check out this page on dynamically invoking constructors.
you could use reflection to check if there is a no arg constructor for the class and fail the test if there is
Yep. A good way would be to use reflection to try a parameterless constructor within a try/catch.

Enforce Attribute Decoration of Classes/Methods

Following on from my recent question on Large, Complex Objects as a Web Service Result. I have been thinking about how I can ensure all future child classes are serializable to XML.
Now, obviously I could implement the IXmlSerializable interface and then chuck a reader/writer to it but I would like to avoid that since it then means I need to instantiate a reader/writer whenever I want to do it, and 99.99% of the time I am going to be working with a string so I may just write my own.
However, to serialize to XML, I am simply decorating the class and its members with the Xml??? attributes ( XmlRoot , XmlElement etc.) and then passing it to the XmlSerializer and a StringWriter to get the string. Which is all good. I intend to put the method to return the string into a generic utility method so I don't need to worry about type etc.
The this that concerns me is this: If I do not decorate the class(es) with the required attributes an error is not thrown until run time.
Is there any way to enforce attribute decoration? Can this be done with FxCop? (I have not used FxCop yet)
UPDATE:
Sorry for the delay in getting this close off guys, lots to do!
Definitely like the idea of using reflection to do it in a test case rather than resorting to FxCop (like to keep everything together).. Fredrik Kalseth's answer was fantastic, thanks for including the code as it probably would have taken me a bit of digging to figure out how to do it myself!
+1 to the other guys for similar suggestions :)
I'd write a unit/integration test that verifies that any class matching some given criteria (ie subclassing X) is decorated appropriately. If you set up your build to run with tests, you can have the build fail when this test fails.
UPDATE: You said, "Looks like I will just have to roll my sleeves up and make sure that the unit tests are collectively maintained" - you don't have to. Just write a general test class that uses reflection to find all classes that needs to be asserted. Something like this:
[TestClass]
public class When_type_inherits_MyObject
{
private readonly List<Type> _types = new List<Type>();
public When_type_inherits_MyObject()
{
// lets find all types that inherit from MyObject, directly or indirectly
foreach(Type type in typeof(MyObject).Assembly.GetTypes())
{
if(type.IsClass && typeof(MyObject).IsAssignableFrom(type))
{
_types.Add(type);
}
}
}
[TestMethod]
public void Properties_have_XmlElement_attribute
{
foreach(Type type in _types)
{
foreach(PropertyInfo property in type.GetProperties())
{
object[] attribs = property.GetCustomAttributes(typeof(XmlElementAttribute), false);
Assert.IsTrue(attribs.Count > 0, "Missing XmlElementAttribute on property " + property.Name + " in type " + type.FullName);
}
}
}
}
You can write unit tests to check for this kind of thing - it basically uses reflection.
Given the fact this is possible I guess it would also be possible to write a FxCop rule, but I've never done such a thing.
You can write an FxCop rule or even check for the attributes by calling GetType() in the base class's constructor and reflecting over the returned type.
A good FXCop rule (and one which I am finding I need right now) would be to check that all objects that are being added to the ASP.NET Session have the Serializable attribute. I'm trying to move from InProc session state to SQL Server. First time I requested a page, my site blew up on me because non-serializable objects were being stored in Session. Then came the task of hunting through all the source code looking for every instance where an object is set in the Session... FXCop would be a nice solution. Something to work on...
You can also use this concept/post-processor to enforce relationships between attributes and use similar login to enforce relationships between classes and attributes at compile time:
http://www.st.informatik.tu-darmstadt.de/database/publications/data/cepa-mezini-gpce04.pdf?id=92

Categories