tags:

views:

78

answers:

5

Hi,

I have a class called FooJob() which runs on a WCF windows service. This class has only 2 public methods, the constructor, and a Run() method.

When clients call my service, a Dim a new instance of the Job class, pass in some parameters to the ctor, then call Run()...

Run() will take the parameters, do some logic, send a (real time) request to an outside data vendor, take the response, do some business logic, then put it in the database...

Is it wise to only write a single unit test then (if even possible) on the Run() function? Or will I wind up killing myself here? In this case then should I drill into the private functions and unit test those of the FooJob() class? But then won't this 'break' the 'only test behavior' / public interface paradigm that some argue for in TDD?

I realize this might be a vague question, but any advice / guidance or points in the right direction would be much appreciated.

Drew

+1  A: 

Hi there.

Simple answer is - it depends. I've written a lot of unit tests that test the behaviour of private methods; I've done this so that I can be happy that I've covered various inputs and scenarios against the methods.

Now, many people think that testing private methods is a bad idea, since it's the public methods that matter. I get this idea, but in my case the public method for these private calls was also just a simple Run() method. The logic of the private methods included reading from config files and performing tasks on the file system, all "behind the scenes".

Had I just created a unit test that called Run() then I would have felt that my tests were incomplete. I used MSTest to create accessors for my class, so that I could call the private methods and create various scenarios (such as what happens when I run out of disk space, etc).

I guess it's each to their own with this private method testing do/or don't do argument. My advice is that, if you feel that your tests are incomplete, in other words, require more coverage, then I'd recommend testing the private methods.

Cheers. Jas.

Jason Evans
+2  A: 

My advice would be to let your tests help with the design of your code. If you are struggling to execute statements or functions then your class is doing too much. Follow the single-responsibility-priciple, add some interfaces (allowing you to mock out the complicated stuff), maybe even read Fowler's 'Refactoring' or Feather's 'Working With Legacy Code', these taught me more about TDD than any other book to date.

Ben
+2  A: 

do some logic, send a (real time) request to an outside data vendor, take the response, do some business logic, then put it in the database

The problem here is that you've listed your class as having multiple responsibilities... to be truly unit testable you need to follow the single responsibility principle. You need to pull those responsibilities out into separate interfaces. Then, you can test your implementations of these interfaces individually (as units). If you find that you can't easily test something your class is doing, another class should probably be doing that.

It seems like you'd need at least the following:

  1. An interface for your business logic.
  2. An interface defining the request to the outside vendor.
  3. An interface for your data repository.

Then you can test that business logic, the process of communicating with the outside vendor, and the process of saving to your database separately. You can then mock out those interfaces for testing your Run() method, simply ensuring that the methods are called as you expect.

To do this properly, the class's dependencies (the interfaces defined above) should ideally be passed in to its constructor (i.e. dependency injection), but that's another story.

ColinD
Thanks... But I have a question - at what point are we over-engineering and building too many classes, when we could just unit test some private functions? Is there any general rule of thumb here? Just go with your gut... ?
dferraro
I'd advise having a look at the SOLID principles of object-oriented design (http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod), of which the Single Responsibility Principle is one. I'd also try not to consider breaking things down into multiple classes to be over-engineering, since each class becomes simpler and more understandable. I'd say "if you feel a need to unit test a private method, it should probably be another class" would be one rule of thumb, as well as what I said above about having to list out the responsibilities of a class.
ColinD
I break apart classes until they can't be broken apart any more. If you avoid return values, and think of classes as sending messages to one another, this becomes a bit easier to conceptualize. Micro-classes have the benefits of being extremely easy to understand, as well as the fact that adding new behavior generally is done by adding more classes, meaning you can leave existing, tested code alone. That's a good thing.
kyoryu
+1  A: 

It sounds like your run method is trying to do too much I would separate it up but if you're overall design won't allow it.

I would consider making the internal members protected then inheriting from the class in your test class to test them. Be careful though I have run into gotchas doing this because it doesn't reset the classes state so Setup and TearDown methods are essential.

L2Type
A: 

Thanks everyone for the comments. I believe you are right - I need to seperate out into more seperate classes. This is one of the first projects im doing using true TDD, in that I did no class design at all and am just writing stub code... I gotta admit, I love writing code like this and the fact I can justify it to my mangagment with years of backed up successful results is purely friggin awesome =).

The only thing I'm iffy about is over-engineering and suffering from class-bloat, when I could have just written unit tests against my private methods... I guess common sense and programmers gut have to be used here... ?

dferraro