|
From: Mike B. <mbr...@vi...> - 2004-01-18 22:41:40
|
I wasn't aware that DynamicMock could be used on any classes. I thought it
only worked on interfaces. Being able to create dynamic mocks of classes
would be super cool. Its annoying to have to create separate interface for
every single class in the application, especially when working with existing
code that did not use mock objects. I don't see the need for calling
constructors though. I would think that a dynamic mock object created from
a class would only have the public methods and properties just as if the
class were an interface. What would a constructor do for us?
Mike Bresnahan
-----Original Message-----
From: nmo...@li...
[mailto:nmo...@li...]On Behalf Of Jim Arnold
Sent: Sunday, January 18, 2004 3:47 PM
To: nmo...@li...
Subject: [Nmock-general] Mocking types with constructors
You're probably all aware of NMock's inability to mock types without default
(empty) constructors. It's been bothering me for a while, given that this
trendy Inversion Of Control lark is driving us to create classes with fatter
constructors, so I decided to do something about it. I am aware that one of
the more important goals of mocking is to drive an interface/implementation
seperated design and that, arguably, expanding the range of classes that we
can mock subverts that goal. However, I don't think many of us would argue
that *every* concrete type should be matched by an interface just for the
sake of it, and we all work with pre-defined classes that are not always
described by interfaces. Furthermore, creating an interface purely to mock
a class is Evil. It is a code smell (a tool smell, really, if you'll pardon
the expression).
The code to allow NMock to support constructors turns out to be trivial, but
it does force the user to choose whether they want to pass parameters
through to the base class or not (yes, even though C# forces you to call a
base constructor, the CLR does not, so you would end up with a
non-initialised base). An example might describe it better. Given the
following class:
public class ClassWithFatConstructor
{
public int Foo;
public string Bar;
public ClassWithFatConstructor(int foo, string bar)
{
Foo = foo;
Bar = bar;
}
}
the following code would create a mock instance without calling the base
constructor:
IMock mock = new DynamicMock(typeof(ClassWithFatConstructor));
ClassWithFatConstructor instance =
(ClassWithFatConstructor)mock.GetInstance(false); //false indicates we don't
want to initialise the base class
We end up with a subclass of ClassWithFatConstructor, with all public
virtual methods mocked as usual, but with all fields in the base class
remaining in an uninitialised, or default state. This means that Foo == 0
and Bar == null, and that calls to unmocked methods which rely on that state
can potentially fail. The next snippet creates a mock instance and ensures
that it calls through to the base:
IMock mock = new DynamicMock(typeof(ClassWithFatConstructor));
ClassWithFatConstructor instance =
(ClassWithFatConstructor)mock.GetInstance(true, 123, "abc");
We now get a properly initialised base. There is one thing that still
bother me about the API though. There's no point passing parameters in if
we *don't* want to call the base constructor - we can just create a default
constructor on the mock and call that instead. So I'd appreciate some
feedback on how this would look.
Anyway, if you got this far, you probably have an opinion on whether this
should be in NMock or not, so let me know what you think and I'll either
post the code or shut up.
Cheers,
Jim
|