views:

354

answers:

8

I'm working on a new project and I'm using the repository pattern, I have my repository that pulls the data from the database and a "service" class which uses the repository and does all the business logic.

something similar to the following;

public class UserRepository : IUserRepository
{
    public IQueryable<User> GetUsers()
    {
    // do stuff
    }
}

public class UserService 
{
    public IList<User> GetUserById
    {
        var rep = new UserRepository();
        var users = rep.GetUsers();
        // do business logic
        return users.ToList();
    }
}

Would you test both the UserService and the UserRepository or do you think testing just the Service would suffice? I figure since the service is using the repository it should be fun, but it does kill code coverage.

A: 

You should test them both. Having tested the repository, it will be easier and more reliable when you go to test the service.

thetacom
+4  A: 

If you've written the code and are only now thinking about the tests, you've already strayed from the True Path of test-driven development :-) That said, if it were my code, I'd write the UserService tests first, then check my code coverage.

Edit in response to comment: If you haven't actually written the code yet, I'd write the tests for UserService first, because that's the ultimate goal of your app. Then as I wrote the code to make the UserService tests pass, I'd spawn off tests of the repository. Those tests eventually become the specification of the repository in case you want to reuse it later.

Norman Ramsey
I haven't wrote the code yet, I'm thinking of the architecture and was getting ready to write the tests and didn't know how much I should
sontek
Ah sorry about that. I'll update.
Norman Ramsey
+9  A: 

You should test them both, because it's possible that someday there will be other clients of UserRepository than UserService, and those clients may use UserRepository differently than UserService.

stevex
+8  A: 

test the features that you require:

  • some features may reside in one class
  • some may reside in the other class
  • some may require both classes

from your description it looks like you get to define the features, so you can pretty much justify testing anything you like ;-)

if you're looking for minimal TDD efficiency, test only the current feature, and move on. Code coverage is not relevant for TDD; that is a unit-testing metric (of questionable value)

[let the downvoting begin! ;-)]

Steven A. Lowe
"let the downvoting begin!" I know you were joking, but I hope that actually doesn't become the case. As with every programming aspect, many take it way too far and seriously. Its not like failing to test some parts means the testing is flawed, and its not like testing is the only way to bug-check.
Spodi
@[Spodi]: i was only half-joking. There are unit testing adherents who would insist on 100% code coverage, up to and including getters and setters. That is NOT what TDD is all about though...
Steven A. Lowe
+1  A: 

You have two options here:

  • Unit Tests - In this case you test each component in isolation without accessing services, disk, databases, active directory, etc. This is achieved by having your tests act as the driver and stubbing out / mocking the classes used by the class you are testing.

  • TDD - This is like unit tests, but in this case you will write your test case, run it to fail, write enough code to get it to pass, run it to confirm it passes, then move on to the next. In this case all the code should be covered.

In your case, it is very important to realize that when testing the UserService, you will test it against DummyRepository which implements IUserRepository. In this case you can fully test the user service without having to access the real underlying repository class / data source. This will produce clear distinction between bugs in your two classes and will give you control to simulate all possible failures for the repository.

You will do the same to test the UserRepository implementation. This is by stubbing out the access to the underlying resource. You can use Mock frameworks which uses profiler API to mock dependencies or by using interfaces / virtual methods to allow a unit test class to override the access to the resource.

In addition to the above white box testing techniques, you still need to do your black box / integration testing. This is where you have some end to end test cases which tests the application scenario as a whole where the UserService interacts with UserRepository which then interacts with the data source.

vboctor
A: 

If you are following the TDD process - as the question title implies - then you won't have both the UserRepository and the UserService classes if there are not tested.

There is an eXtreme Programming saying: "Test everything that could possibly break", so you're better off testing them all so that you could feel confident about your code.

philippe
A: 

As others have already mentioned, if UserService is all that the clients of your application are going to see, I'd only test that for now and make UserRepository inaccessible to your clients (e.g. make it internal). This way you should get good code coverage even without testing the classes individually.

If your code coverage is bad, this usually either means that your tests are insufficient or you have implemented stuff that cannot be invoked through the public interface and could therefore likely be removed.

Andreas Huber
A: 

Write Service unit tests by mocking Repository to test the business logic in Service and to test different Repository scenarios like Exception, test return values etc. Some mocking frameworks like EasyMock require a Repository interface while others like Mockito dont. This way your Service tests wont access DB and will execute faster.

Write Repository tests to test all your DB interactions. Use DB unit dataset/fixtures for test data to ensure your DB logic is implemented correctly.

Additonally you may want to write integration tests on your Service class where DB is accessed without mocking Repository.

Sathish