views:

79

answers:

6

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?

+10  A: 

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));
}
womp
A: 

you could use reflection to check if there is a no arg constructor for the class and fail the test if there is

Sam Holder
+8  A: 

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.

No Refunds No Returns
I prefer this way over the Unit Test concept in this case because Unit Tests often times fall by the wayside, whereas code with comments is there right in your face when you try to change it. After all, you're not trying to test functionality in this case, but rather programming style or a programming norm, which is not really what a Unit Test is for.
Nick
I prefer a combination of both. I always postulate that tests should have the business reason documented. The good thing about the test though, is that it forces compliance by breaking the build. Documentation does not.
womp
+5  A: 
ConstructorInfo ci = typeof(MyClass).GetConstructor(Type.EmptyTypes);
Assert.IsNull(ci);
plinth
A: 

Yep. A good way would be to use reflection to try a parameterless constructor within a try/catch.

Nick W