Difference between Dependency Injection and Mocking Framework (Ninject vs RhinoMocks or Moq)

后端 未结 2 1889
你的背包
你的背包 2020-12-02 05:41

What is the difference between Ninject and a mocking framework like RhinoMocks or Moq? I Google\'d this but it is still unclear.

相关标签:
2条回答
  • 2020-12-02 06:21

    Ninject is Dependency Injection for .NET.

    RhinoMocks and Moq are both mocking frameworks.

    Now both have nothing to do with each other. I really had trouble understanding both so here I go trying to explain.

    Dependency Injection: is an implementation (lets call it) of Inversion of Control. You don't confuse the two. You are taking the control of creating an object out of your code. Dependencies, like say a IRepository would not be created by your classes/code but instead injected by someone else, a dependency injection framework.

    Lets say you have

    interface IUserRepository
    {
     string GetUserName(int id);//one method for simplicity
    }
    

    Now you have an actual implementation:

    class MyUserRepo : IUserRepository
    {
     string GetUserName(int id)
     {
      //grab your username from your data base here.
     } 
    }
    

    Now all over the place, you'll have:

    IUserRepository repo = new MyUserRepo();//this is bad!!
    

    Why? Ask yourself why you made an interface in the first place? So you can cope with change. Well now, when you need to change your repository to something else. You have to replace all the lines that have new MyUserRepo().

    A simple method is user a factory method which is another form of IOC.

    class RepoFactory
    {
     public static IUserRepository UserRepo
     {
      get {return MyUserRepo();}
     } 
    }
    

    And use it like this:

    IUserRepository rep = RepoFactory.UserRepo;
    

    Now when you have to change your repository you have to change only your factory. Dependency injection takes this to the next level by doing all the work. You don't need to change the code at all (or maybe a few declarations).

    IUserRepository repo; 
    //this magically gets the right instance based on some config somewhere.
    

    A Mocking Framework : Boy this was like rocket science to me. But Steven Sandersons book had a brilliant simple explanation.

    We keep going on with the IUserRepository.

    Now you have to test some complicated UI/Authentication whatever that depends on IUserRepository.

    class UserDisplay : UserControl
    {
      UserDisplay(IUserRepository repo)
      {//display the username or something here..
      } 
    }
    

    Now in your test, when you make IUserRepository an instance of MyUserRepo. If something goes wrong you don't know what went wrong! Was it your user control or your database connection?

    You want make the test more deterministic as someone said.

    So you make a fake user repository.

    class FakeUserRepo : IUserRepository
    {
      public string GetUserName(int id)
      {
        return "FakeUser";
       }
    }
    

    So now, when you pass this fake repo. If you're test fails you KNOW it was something else, not the data base.

    My example was simple, but if its a large number of Interfaces. You'll need to write a lot of fake code, its a lot of code bloat!

    So you can use a mocking framework to write less code here.

    Moq uses a fluent interface and is quite nice. Using Moq would look like this:

    var fakeUserRepo = new Mock<IUserRepository>();
    fakeUserRepo.Setup(f => f.GetUserName(It.IsAny<int>)).Returns("FakeUser");
    //does the same thing as the class declaration
    fakeUserRepo.Object;//this returns fake object of type IUserRepository
    

    Creating fake objects becomes a lot easier =)

    Now I hope your seeing how you can use both to your advantage. You can create your fake objects with a mocking framework, then use dependency injection to hook up the right objects at the right time.

    For my smaller Silverlight applications I use MEF (Inbuilt in .Net4) for Dependency Injection. And then I have little #Ifdef on the declarations for which classes to Export (or expose) Based on a #define symbol. So I just change one #define and I can switch my app to using fake classes here and there.

    Really Hope that was helpful.

    0 讨论(0)
  • 2020-12-02 06:26

    Ninject is a dependency injection/inversion of control tool. You use this to manage dependencies between classes.

    The classic example is if you have something like a service or a data repository. Instead of using a concrete class throughout the application, you can ask the Ninject kernel to get you an instance of an interface. This means you can make multiple concrete classes that implement the interface, and swap them out in a single place. This is extremely useful in testing, but goes far beyond that. Lots of IoC containers, Ninject being no exception, will also do things like manage instance lifecycles and a host of other stuff. Say if you want to use 1 repository per web request, or a single instance of a class, that's the kind of thing Ninject can take care of for you very cleanly.

    Moq, RhinoMocks etc are mocking frameworks, they generate fake classes for you to assert that other parts of the application interact with them in the correct way. These are really only useful for testing because the mocked objects don't provide any functionality beyond reporting back on how they were accessed.

    You might also want to check out StructureMap - structuremap.net/structuremap - they have some good articles describing the pattern, and also Rob Conery does episodes on IoC - http://www.asp.net/mvc/videos/aspnet-mvc-storefront-part-13-dependency-injection - and on Mocking - http://www.asp.net/mvc/videos/aspnet-mvc-storefront-part-12-mocking - which are a good watch and describe far better than I can what each are about.

    0 讨论(0)
提交回复
热议问题