views:

52

answers:

3

Hi,

First of all let me say I am working from legacy code. So some changes can be made but not drastic ones.

My problem is I have a "Vehicle" object, it is pretty simple but has no interfaces or anything on it. This project was created before TDD really started to become more main stream. Anyway, I need to add a new method to change the starting mileage of the vehicle. I thought this would be a good start to try TDD and Mocking as I am new it all. My problem is I need to create a vehicle do some checks which involve going to the database. Sorry if my question is not 100% clear, is why I am posting as I am a bit confused where Rhino Mocks fits in (and if I need it!).

+2  A: 

The problem is dependencies. Your vehicle class depends on the database. Hopefully all the interactions with the database have been encapsulated into a nice class we will get back to that in a second. When you fire off your unit test you want to be able to test the vehicle class without having to care about the database. For example you want to check that your SpeedUp(int x) method really increases the total speed by x. In this method the first thing it does is it asks the DB for its current speed. That means that you have to have a DB to test! Dam, that doesn't sound like a very fast test nor repeatable. Also a lot of setup to just run a test.

Wouldn't it be great if we could have a pretend DB? That is where mocking comes in. We create a Mock of the class that has all the DB interaction encapsulated. We then setup the mock to respond with a prepgrammed value. So for example when we ask the DB for current speed you return 100.

So now when we test the mock returns a 100 and we can assert that SpeedUp(int x) takes 100 and adds x to it.

uriDium
A: 

Is it easy to create an instance of the Vehicle type (an object) and then invoke your method for a test ? If yes, then chances are you don't need a mock.

However if your Vehicle type has dependencies (like a Database access object) that it needs to perform the action that you want to test, then you would like to use a mock database access object that returns canned values for the test since you want your unit tests to run fast.

Vehicle  [depends On>] OwnerRepository [satisfied By] SQLOwnerRepository

So you introduce an interface (an OwnerRepository to get details of the owner, let's say) to separate the DB Interaction (define a contract) between the two. Make your real dependency (here SQLOwnerRepository) implement this interface. Also design your code such that dependencies can be injected e.g.

public Vehicle (OwnerRepository ownerRepository) 
{  _ownerRepository = ownerRepository;  // cache in member variable }

Now in the test code,

Vehicle [depends On >] OwnerRepository [satisifed By] MockOwnerRepository 

You have frameworks that given an interface would create a mock implementation of it (See Rhino/Moq frameworks). So you no longer need an actual DB connection to test your Vehicle class. Mocks are used to abstract away time consuming / uncontrollable dependencies in order to keep your unit tests fast / predictable.

I'd recommend reading up on "Dependency Injection" to have a better understanding of when and why to use mocks.

Gishu
+1  A: 

Rhino mocks can only create mocks from interfaces or abstract classes, which do not exist your legacy code.

TypeMock can mock anything but isn't free.

You could use Microsoft Moles to mock these out.

You should however take into account that Moles should be your last resort solution, it's better to refactor your code and make it testable by abstracting your datalayer from your business layer.

HTH

Stephane