“I’m sometimes feel as if I’m selling snake oil the solution is dependency injection”.
Don’t you think it would be a good idea to override the class loading process in Java or something ? So that it would actually be possible to mock static calls like new operator or static methods. For C++ M.Feathers in his book suggested to use the link time seam to inject doubles your code depends on.
I think something like that is already possible in .NET with Roy Osherove’s Typemock framework – he claims he exploited .NET’s introspection API.
Some inner voice of myself is telling me you could write another article “Static I love you but you have to go”
najcik: Does anybody actually love statics, though? I guess what I’m trying to get at is the question, “why would we want to mock statics in the first place?”
TypeMock sounds like a superb product for breaking dependencies on code you have no control over, but I would never advocate using it to break dependencies that shouldn’t exist in the first (i.e. global/static state). I don’t think even Roy Osherove (a TypeMock developer) advocates using TypeMock to isolate static state unless the developer has no control over it.
Automated testing is a microcosm of using the software. If we cannot understand the dependencies in a unit test, then it’s obviously too hard to understand/develop against in practice. I.e. if we create artificial seams in a test using a specialised tool, we are merely papering over the cracks. The real problem still exists — the static/global state is still there making developers’ lives difficult.
@najcik: There are a few smart(?) people saying that DI is not the only solution to testability. But on the other hand printers don’t build themselves. Let factories build printers. It makes your code more readable, understandable. You have separated responsibilities for building objects and doing something in objects. It’s the same as separating UI from domain. You can do it otherway but most of the time it turns out to be a disaster.
Good talk, I originally have trouble with DI before realizing factories could be injected for the creation of objects with shorter lifetimes.
@najcik: to substituting new operators or static calls by interception seems global state. What if you have two new calls of the same class and want to inject two mocks with different behavior?
I’m still struggeling with how to use the DI aspect in production.
The example with the Login Page you gave and the @Cookie annotation.
From testing creating the LoginPage is obvious, but how does this looks like in production code, where I need different LoginPages with different cookies.
And how does this go straight with your post about injectables und newables ? didnt you advice NOT to mix them ? The loginpage does mix it (String & Authenticator).
So for me this is the dilemma… I dont understand how to solve this problem with DI.
@Zilvinas, @Mark
I do agree with both of you. Really sign under your comments with both my hands But there will always be code you have to cope with and which is not up to the standards, you have to start with something – even Mr. Feathers suggests that you’ll have to do some initial refactoring of the legacy code without tests because it might not be feasible to do otherwise. I certainly don’t advocate to not use DI here just thought a feature like of a mocking framework could be warm welcomed by testers.
@Giorgio Sironi – Well, you can mock subseqent calls and tell the fake to behave differently on each call, can’t you ? If new was mockable how could it be any different ? So I would like alter the behavior of the loader and pass loader mock such that if a new operator is called it loads a different class. If another new is called to create an object of the same class it can be another fake with the behavior needed for the second call.
Good talk, as usual. Sums up really well most of your post. I have a question tho.
What happen when object A needs another object B in a certain state? Most of the time, this as to do with network connection, i.e when Object B needs to be connected to some end-point to be used by object A.
@misko, this is what I thought, but my network connection object “A” is asynchronous (AS3). My object “B” needs a connected object “A” so my factory will need to be asynchronous (?) and handle connection errors. Is it really the place for that stuff?
12 responses so far ↓
“I’m sometimes feel as if I’m selling snake oil the solution is dependency injection”.
Don’t you think it would be a good idea to override the class loading process in Java or something ? So that it would actually be possible to mock static calls like new operator or static methods. For C++ M.Feathers in his book suggested to use the link time seam to inject doubles your code depends on.
I think something like that is already possible in .NET with Roy Osherove’s Typemock framework – he claims he exploited .NET’s introspection API.
Some inner voice of myself is telling me you could write another article “Static I love you but you have to go”
najcik: Does anybody actually love statics, though? I guess what I’m trying to get at is the question, “why would we want to mock statics in the first place?”
TypeMock sounds like a superb product for breaking dependencies on code you have no control over, but I would never advocate using it to break dependencies that shouldn’t exist in the first (i.e. global/static state). I don’t think even Roy Osherove (a TypeMock developer) advocates using TypeMock to isolate static state unless the developer has no control over it.
Automated testing is a microcosm of using the software. If we cannot understand the dependencies in a unit test, then it’s obviously too hard to understand/develop against in practice. I.e. if we create artificial seams in a test using a specialised tool, we are merely papering over the cracks. The real problem still exists — the static/global state is still there making developers’ lives difficult.
@najcik: There are a few smart(?) people saying that DI is not the only solution to testability. But on the other hand printers don’t build themselves. Let factories build printers. It makes your code more readable, understandable. You have separated responsibilities for building objects and doing something in objects. It’s the same as separating UI from domain. You can do it otherway but most of the time it turns out to be a disaster.
Good talk, I originally have trouble with DI before realizing factories could be injected for the creation of objects with shorter lifetimes.
@najcik: to substituting new operators or static calls by interception seems global state. What if you have two new calls of the same class and want to inject two mocks with different behavior?
I’m still struggeling with how to use the DI aspect in production.
The example with the Login Page you gave and the @Cookie annotation.
From testing creating the LoginPage is obvious, but how does this looks like in production code, where I need different LoginPages with different cookies.
And how does this go straight with your post about injectables und newables ? didnt you advice NOT to mix them ? The loginpage does mix it (String & Authenticator).
So for me this is the dilemma… I dont understand how to solve this problem with DI.
Thanks
@Zilvinas, @Mark
But there will always be code you have to cope with and which is not up to the standards, you have to start with something – even Mr. Feathers suggests that you’ll have to do some initial refactoring of the legacy code without tests because it might not be feasible to do otherwise. I certainly don’t advocate to not use DI here just thought a feature like of a mocking framework could be warm welcomed by testers.
I do agree with both of you. Really sign under your comments with both my hands
@Giorgio Sironi – Well, you can mock subseqent calls and tell the fake to behave differently on each call, can’t you ? If new was mockable how could it be any different ? So I would like alter the behavior of the loader and pass loader mock such that if a new operator is called it loads a different class. If another new is called to create an object of the same class it can be another fake with the behavior needed for the second call.
igorbrejc.net » Fresh Catch For October 12th // Oct 11, 2009 at 10:07 pm
[...] Design for Testability Talk [...]
Is there an audio recording that I could play/download. Video download is are a bit much for my connection.
Good talk, as usual. Sums up really well most of your post. I have a question tho.
What happen when object A needs another object B in a certain state? Most of the time, this as to do with network connection, i.e when Object B needs to be connected to some end-point to be used by object A.
How do you deal with this kind of dependency?
@Subb, it is up to the factory, to make sure that the object is injected in the right state.
@misko, this is what I thought, but my network connection object “A” is asynchronous (AS3). My object “B” needs a connected object “A” so my factory will need to be asynchronous (?) and handle connection errors. Is it really the place for that stuff?
Thanks Misko, it’s really great talk.