views:

146

answers:

2

IMO one of the main characteristics of a good TDD is: testing your class (or actually unit) in isolation.

When you do so, you are able to actually test single behavior in each test -- only one test will fall for a single problem you have.

For this you first must verify that there are no static references from your class (including constructors AKA new keyword).

in theory it is easy not to use any dependency injection framework and test your classes in complete isolation, for this you need to inject all dependencies in the constructor and create Factories classes that will call the new keyword.

I found this theoretical MO to be too hard to actually do in practice.

Am I missing something important in the process?

EDIT: I do think that we should all aim to one failure for one code change. it will never be perfect but it will get your code closer to there, people forget that test code is also maintainable code, specification of tested code changes.

If you don't aim there you will end up deleting tests which is a poor solution

+8  A: 

I don't think you need DI frameworks for unit testing - TDD has been around years before DI became a fashion. And in case of code which does not use an explicit DI framework itself, why would you use that for unit tests?

Sure, DI frameworks can simplify the task to some extent. OTOH they do it by putting the complexity elsewhere. My preference is to have self-containing unit tests, and so far I have almost always managed without a DI framework. That often requires refactoring my test code, and sometimes even duplicating code, but I can live with that. And, as @kostja noted, mocking frameworks are a big help too.

Designing for testability is important too - if a class is hard to test per se, it is better to refactor it rather than trying to alleviate the pain with a DI framework.

Note that all this requires lots of practice, as well as a change in mindset and ways of thinking. All of which takes time and patience... the more you keep up, the better you become :-)

you are able to actually test single behavior in each test -- only one test will fall for a single problem you have.

I think your conclusion is wrong here. Even if you test a single thing in each test, you can break a lot of tests with a single code change. Update: Every test is to verify a single path of execution within the tested code. However, those paths of execution are rarely independent - there tend to be common path sections in all but the simplest methods. Any change there can break multiple tests.

Péter Török
Thanks for you answer and editing. I use mocking allot in order to isolate what I test, I think we should all aim for a single code change single test failure, off-course it is impossible. I do you inject your dependencies in the constructor or do you have new inside your non-factories code?
ekeren
@ekeren, I work with legacy code so anything is allowed :-) as long as it helps writing unit tests. I do DI through constructors, special setters, even via subclass methods overridden specifically for unit testing. See [Working Effectively with Legacy Code](http://www.amazon.co.uk/Working-Effectively-Legacy-Robert-Martin/dp/0131177052) for details.
Péter Török
+1 for objecting to the conclusion that only a single test will fail for a given problem.
jvenema
@ekeren, a single test failure for a single code change is indeed unrealistic - see the extended explanation in my answer.
Péter Török
Working Effectively with Legacy Code is my bible (along with Effective Java :)) . I don't like doing overrides when I can inject dependency in constructors so when I do new code I try to move my DI to constructors, Thanks for you answer.I do think that we should all aim (and people seldom do) to one failure for one change. it will never be perfect
ekeren
@ekeren, of course, overrides and similar nasty tricks are a last resort. But with legacy code, sometimes I need these. Regarding failures per change, I think it is not really relevant after all - all of us aim to have our unit tests 100% green, don't we? So I don't really care how many of my unit tests fail if there is a bug - I just go and fix it, then enjoy the green light again :-)
Péter Török
+1  A: 

DI is supposed to reduce direct dependencies, actually simplifying mocking and unit testing. Maybe you are missing the mock part? this post could clarify things.

kostja
Thanks for your answer. I using mocking allot, I don't think you can do good TDD without using mocks, or at least making up your own mocks
ekeren