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...
Roy.
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));
To this:
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.