A: 

You could use an IOC container and then register a different repository.

Jon Masters
+8  A: 

Dependency Injection can come in really handy for these kinds of things:

public class RegistrationService: IRegistrationService
{
    public void Register(User user)
    {
        this(user, new UserRepository());
    }

    public void Register(User user, IRepository<User> userRepository)
    {
        // add user, etc
    }

}

This way you get the ability to use UserRepository as your default, and pass in a custom (Mock or Stub for testing) IRepository for whatever else you need. You may also want to change the scoping of the 2nd register method in case you don't want to expose it to everything.

An even better alternative would be to use an IoC container which would buy you syntax that is even more decoupled than the above example. You could get something like this:

public class RegistrationService: IRegistrationService
{
    public void Register(User user)
    {
        this(user, IoC.Resolve<IRepository<User>>());
    }

    public void Register(User user, IRepository<User> userRepository)
    {
        // add user, etc
    }

}

There are many IoC containers out there, as listed by other people's answers, or you could roll your own.

Joseph
This looks pretty good but has the drawback that I would need to create a 2nd method with userRepository parameter for every method in RegistrationService...
Alex
@Alex That is correct. If you didn't want to do that you could alternatively inject the repository in your constructor, but you were shying away from that in your question.
Joseph
@Alex However, also note that one of the methods is only a wrapper to define the "default" behavior, and doesn't have any real behavior in it.
Joseph
I can't say I like your second method, wherein you attempt to resolve the IRepo. This doesn't really buy you a lot, since you are then creating a dependency on the IOC container...
Chad Ruppert
@Chad That's true with ANY IoC container that you use. You will eventually have to create a dependency on SOMETHING, the question is, what THING do you want to be dependent on? In the first case, RegistrationService is dependent on UserRepository. In the second case, RegistrationService is dependent on IoC (whatever that is). It's kind of a "pick your poison" scenario, to be sure.
Joseph
Why do you have to be dependent on your IOC Container? I use Unity, and it looks for constructors and does it automagically, sure I have to register them, but there is no Unity code in ANY of my domain or service layers. Purely in the ui/application(read web) layer. RegistrationService should be dependant on an IRepo, as you have done, however if Ninject or Windsor comes out with a kick-rear new feature, I certainly don't want to have to modify all of my service/domain classes simply for popping out what is in reality a convenience tool.
Chad Ruppert
@Chad I'm not advocating dependancy on Unity, or Ninject, or StructureMap, or any specific IoC container. What I mean to illustrate here is that you will have to have some construct by which to resolve an interface (in this case IRepository<User>). In my answer I chose to denote that as IoC.Resolve... With my earlier comment, I was trying to get at the bigger point that you will become dependent on something at some point, so you'll have to make a choice one way or the other (you chose Unity for instance). The first example I did chose to be dependent on the UserRepository itself.
Joseph
I'm not taking issue with your statement that you have to be dependent on something. What I take issue with in your second method, is that you now become dependent on BOTH the SPECIFIC implementation of the IOC container and some implementation of repo. You simply cannot get away from *a* repository being needed. I would hate to see someone use this second example, and get hosed down the line because they actually try to resolve INSIDE of the class. IOC should be done externally, IMO, otherwise you are defeating the purpose of it. Wouldn't you agree to that?
Chad Ruppert
@Chad I think now I understand the miscommunication. The second example does NOT use a specific implementation of any IoC Container, NOR does it use a any implementation of IRepository<User> (in this case UserRepository). IoC.Resolve could just as well be a wrapper. In fact, it very well should be. Also, the second example knows nothing of UserRepository, which the first example does. That was the whole point of the second example, to show how you would remove the dependency of UserRepository.
Joseph
True there, I did believe that you were doing the IoC.Resolve bit as an actual IOC container. Even if it's a wrapper though, it's still something you need to get to the class, even if it's static as you demonstrate. Are you using an IOC container to inject the IOC container into the wrapper? :) Either way, thank you for the healthy debate. I think that our discussion clears up any issue that I feared might result. I don't really believe we are in real disagreement at all, and your advice is sound, just that little bit just sticks in my craw. Even then it's not awful, just opinion.
Chad Ruppert
@Chad Thank you as well. I always appreciate a good discussion! To be honest, the only reason I would do the IoC resolution inside a class as described is if I was exposing it externally for some reason. Say for instance RegistrationService was being exposed as a WCF service or something. I wouldn't want consumers of said service to have to pass in their own implementation of IRepository<User>, that would be terrible! But in general, injecting the dependency is good practice I believe.
Joseph
A: 

My suggestion would still be to move the repository to a class parameter, and use an IoC container to inject the repository when needed. This way, the code is simple and testable.

Eduardo Scoz
+2  A: 

What you should be doing is using Inversion of Control or Dependency injection.

Your classes shouldn't be tied to an implementation of another class, particularly across layers like this, rather it should take the an interface representing a user repository as either a constructor, or as a property. Then when it runs, you supply the concrete implementation and it uses that. You can build fakes then that implement the repository interface and supply them at test time.

There are very many IOC containers, Unity, Ninject, Castle Windsor, and StructureMap to name a few.


I just wanted to be clear, during your unit tests, I don't know that you'd want to actually use the IOC Container. Integration tests, sure, but for the unit tests, just new up the object you are testing and provide your fake during that process. IOC containers are, at least IMO, there to help out at the application or integration testing levels, and make configuration there easier.

Your unit tests should probably stay 'pure' and just work with the objects you are trying to test. At least that's what works for me.

Chad Ruppert
+11  A: 

You need to use Dependency Injection. UserRepository is a dependency of your RegistrationService class. To make your classes properly unit testable (i.e. in isolation of their dependencies), you need to "invert" what controls your dependency creation. Currently, you have direct control, and are creating them internally. Just invert that control, and allow something external (such as an IoC container like Castle Windsor) inject them:

public class RegistrationService: IRegistrationService
{
    public RegistrationService(IRepository<User> userRepo)
    {
        m_userRepo = userRepo;
    }

    private IRepository<User> m_userRepo;

    public void Register(User user)
    {
        // add user, etc with m_userRepo
    }
}

I think I forgot to add. Once you allow your dependencies to be injected, you open up the possability of them being mockable. Since your RegistrationService now takes its dependent user repository as input to its constructor, you can create a mock repository and pass that in, instead of an actual repository.

jrista
I guess this is the way to go then... I didn't want to have my IRepository's as a class variable, but I guess for injection it's the way to go and then overload the constructor. Thanks!
Alex
Instead of injecting the repo itself, you could inject a factory, and create the repo on demand from that.
jrista
+1  A: 

Just to add a bit of clarity (or perhaps not) to what everyone said, the way an IOC basically works is you tell it to replace X with Y. So what you would do is accept IRepository (as others have stated) as a param and then within the IOC you would tell it to replace IRepository with MockedRepository (for instance) for that specific class.

If you use an IoC that allows for web.config initialization, it makes transitioning from dev to prod very smooth. You simply modify the appropriate params within the config file and you are on your way - without needing to touch the code. Later, if you decide you want to move to a different data source - you just switch it out and you are on your way.

IoC is some fun-lovin stuff.

On a side note, you could do it without IOC injection as well if all you want to do is Unit Test. You could do this by overloading the constructor to accept an IRepository and just passing your mocked repo that way.

Chance
Thank you for the additional information on IOC :)
Alex
+1  A: 

I'm working on something, well, almost verbatim at the moment. I'm using MOQ to mock up a proxy instance of my IUserDataRepository.

From the testing perspective:

//arrange
var mockrepository = new Mock<IUserDataRepository>();
// InsertUser method takes a MembershipUser and a string Role
mockrepository.Setup( repos => repos.InsertUser( It.IsAny<MembershipUser>(), It.IsAny<string>() ) ).AtMostOnce();

//act
var service = new UserService( mockrepository.Object );
var createResult = service.CreateUser( new MembershipUser(), "WebUser" );

//assert
Assert.AreEqual( MembershipCreateUserResult.Success, createResult );
mockrepository.VerifyAll();

MOQ can also be used to throw specific exceptions as well so that my UserService can be tested under those situations.

Then like as others have mentioned IoC will handle the required depenancies. In this case creating a real repository for the UserService class.

MotoWilliams