You know what I'd love to see you post is a code sample
using the natural mocks syntax and one using the "full
power" syntax.
It sounds like you're saying the programming model for
writing tests using one approach vs the other in
TypeMocks are different enough that you know when you're
doing one thing or the other.
In other words, if you're writing new code, you won't
"accidentally" be able to test something that's normally
not testable by accident, thus perhaps cutting off an
extensibility point. You have to consciously choose to
use the more powerful approach for testing something
like legacy code.
Is that a fair characterization?
Old decision process
-Design some functionality that requires a single
instance of something
-I will use a static class
-I want to test something that consumes the single
instance
-Oh wait I can’t mock a static class
-I better use settable singleton or dependency injection
through configuration.
Now it works but is more complicated because I need to
make it testable
Decision process with TypeMock
-Design some functionality that requires a single
instance of something
-I will use a static class
-I want to test something that consumes the single
instance
-I will mock the static class using type mock
Now it works with no custom dependency injection
framework or other code.
Do you understand what I am getting at? How can the
logic be “don’t use TypeMock because that is not
designing for testability”? TypeMock is facilitating
that testability. If you can test something with
TypeMock you are by definition designing for
testability.
Now the only bad thing is that you are tying yourself to
a testing tool. But that is the case no matter what tool
you use. Each can facilitate you testing different
things. Does “designing for testability” really mean
“Design for testability if u only have the simplest
toolset to help you”?
In order to avoid the FUD problem you can use the
following:
• Use different GUI presentation (icon, color, ext…) for
test that may not apply to the TDD (and It can have
different level from best practice to mal practice)
• Filter the test by their best to mal practice category
so the tester can write any kind to test but the
architect can validate upon the tests that will not
bypass the TDD
I think everything you have said is correct, with a
small proviso:
"If you were doing bad design before, the tool won't
help you, just the technique"
The issue is with people just picking up TDD or mocking.
They see that there is a way to mock a static class, and
do it. The thought never occurs to them that it probably
shouldn't be there in the first place. And because of
that, when you try to then say "well I prefer to use an
IoC container here to remove this dependency", they use
the test as a justification of why you dont need to
invert it, after all if we don't need to do it for
testability, and our application probably won't have
that logic replaced in future, why bother? We can just
use the clever trick that TypeMock does if we *ever* see
a need to replace it.
This pretty much comes from a paraphrase of a real
example where I am working right now - where resistance
to good design principles, and TDD, and mocking is
pretty high. I think TypeMock would make some of my code
*much easier* to test (where it depends on systems like
MOSS), but for our own code I could see it being abused
frequently.
It is that tricky balancing act to play - give people
all the power in the world and trust them to use it
safely, or don;t let them have it until they have a
business (and technical) argument for using it.
I love this quote "lose sight of design decisions about
making the code testable in the first place". To me this
sums up what I perceive as a huge problem with many
people in the current Agile/XP world: creating testable
code is a means to an end, it is not the ultimate goal.
The easier it is to create testable code (because the
testing tools are better), then I have more freedom to
choose the best design to solve the business problem,
instead of trying to find the best design to solve the
testing problem. The two concepts are not the same.
The real compelling argument for TypeMock is the legacy
code argument. When I starting a new project, I would
probably pick Rhino.
For me, this is about using the right tool for the right
job. For new development, I find RhinoMocks to be the
right tool. But, I've done enough with legacy code to
know that having the functionality that TypeMock
provides is very useful when working against someone
else's libraries that were obviously not written with
testability in mind.