When testing the constructors, it creates instances of all the parameters types and test the properties using these instances.
From the source code:
"default: return Activator.CreateInstance(type);"
What if my constructor gets an abstract (or an interface) instance?
Well. I've tried it with this constructor:
public Dummy(IContainer someContainer).
The test fails with a "MissingMethodException" (Cannot create an instance of an interface).
I normally don't post comments on blogs, especially making a comment to a comment. But Adrian your comment just seems a bit harsh and comments like this are probably the #1 reason more people don't post good ideas and their code. Other folks come along and the first thing they do is criticize someone's effort.
Rather than posting how to break the original author's idea, why not start off with something like, "Hey this is a good start. Do you have any ideas on how this could be extended to support abstract or interfaces in the constructor arguments?" That is much more constructive and can really get a good discussion started.
The originally post clearly states that this code should be considered sample code, not something that will solve all your problems.
Sorry, off the soap box now.
Thanks Kelly. I think it's a fine point. Adrian - Perhaps you could add that ability...
Creating an instance of an interface is easy using a dynamic proxy.
We can just implement a RealProxy and use it to create instances of any interface.
The problem arrives when we need to actually call methods from that proxy.
One such method is the "Equals" method (It's in every interface...). The ClassTester calls that method somewhere, so we need to implement the proxy invoker of RealProxy (otherwise - we can just leave it "NotImplemented").
Another problem is with abstract classes.
Only MarshalByRef classes can have proxies.
Anyway, because the ClassTester is supposed to run in a testing environment, we can add a reference to nunit.mocks and use their DynamicMock. It's the same, but with the proxy methods implemented. Well, at least "Equals".
After changing the previous "Activator.CreateInstance" call to this code:
And fixing this code:
bool testSet = property.CanWrite && (HasDefaultConstructor(property.PropertyType) || property.PropertyType == typeof(String));
bool testSet = property.CanWrite;
We can add the RaiseEvent call to the "InterfaceProperty" setter and see all tests pass.
We can even create an abstract class property, as the interface, and see it fail or pass, and that depends on whether the class is MarshalByRef or not.
A proxy to a not-MarshalByRef abstract:
I don't have a clue on that. Anyone?
Adrian, if you'd have posted the comment on the blog that offers the source (mine) I'd have been able to reply in a more timely and direct fashion.
Firstly, thanks to Kelly for his response. I couldn't have put it better myself.
Secondly, I think you're missing the point of the ClassTester. It's for the most basic of cases, anything else requires a manual test. Admittedly, the TestConstructors functionality is less well implemented but I have use for it.
Regarding ClassTester, Interesting how some people are trying to write unit tests differently than the xUnit way.
I created QuickUnit.net, it is different from ClassTester idea, but it is in the same world.