Results 1 to 12 of 12

Thread: Interfaces, DI/IoC, unit testing

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Aug 2003
    Location
    Edinburgh, UK
    Posts
    2,773

    Interfaces, DI/IoC, unit testing

    So I know about these things however recently I keep thinking FAR too deep into things and I am now a little confused myself. I wonder if someone can help me untangle myself.

    in your n-Tier design, for the sake of argument lets use this:

    UI
    BLL
    DAL
    Common (which contains entities/DTO's)

    Why would you want to use interfaces between the UI, BLL and DAL?
    I understand it from a Factory design pattern POV (point of view) where it can return an interface, depending on the parameters/configuration it will create a different concrete type - thats cool.

    But other than that, why would you want to use interfaces here and how is it beneficial?

    What about things like unit testing and mocking? you can easily using mocking to mock concrete classes rather than the interface itself and use that for unit testing. So why would you want to use interfaces for unit testing?

    Finally, about DI/IoC - how is this beneficial? Isnt it the same as kind of like a factory pattern where depending on the IoC config, it will return you an instance of the specified concrete class in a certain assembly?

    Arguments/debates please! I am a little confused within myself about this. Too many options and I know there is no one size fits all but would be good to have a discssion about this and why use x or y instead of z, the pros and cons about it.

    MVP 2007-2010 any chance of a regain?
    Professional Software Developer and Infrastructure Engineer.

  2. #2
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: Interfaces, DI/IoC, unit testing

    It's not easy to mock a concrete class. Unit testing a class that has internal dependencies that are concrete classes is a huge pain. Injecting dependencies via interfaces makes it very easy. The whole point is decoupling classes. When each class is basically independent, maintenance becomes easier and testing becomes easier.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  3. #3

    Thread Starter
    PowerPoster
    Join Date
    Aug 2003
    Location
    Edinburgh, UK
    Posts
    2,773

    Re: Interfaces, DI/IoC, unit testing

    gotcha. But with unit testing, you arent really testing the mock - you are testing the functionality (i.e you feed in data to the method, it does what it needs to do and you compare that with what your "manual" expected result should be).

    Can you elaborate, if possible with some examples, on what you mean by internal dependancies along with injecting dependancies via interfaces?

    for example we could have:

    UI -> BLL -> DAL

    UI needs to know the entry point into the BLL to do the business. So it would do:

    Code:
    var myBLL = new MyBusinessLogic();
    MyBusinessLogic() constructor would construct the DAL:

    Code:
    public MyBusinessLogic()
    {
       this.mDBAccess = new DBAccess(ConfigurationManager.ConnectionStrings[Common.Strings.ConnStr]).ConnectionString); // you get the point
    }

    MyBusinessLogic may have methods like:

    Code:
    public LoginUserResponse LoginUser(LoginUserRequest request)
    {
       // sake of argument, forget try catch
       var userData = this.mDBAccess.LoginUser(request.Username, Security.EncryptPass(request.Pass));
       return new LoginUserResponse { User = userData, ValidationErrors = null };
    }

    you get the jist here.

    The BLL should never get the DAL given to it in the constructor via the UI - the UI should not know anything about anything but the BLL when it comes down to it.
    We have a dependancy on the BLL where it depends on the DAL - so when you say "Injecting dependancies via interfaces makes it easy" - how so in the above example?

    MVP 2007-2010 any chance of a regain?
    Professional Software Developer and Infrastructure Engineer.

  4. #4
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: Interfaces, DI/IoC, unit testing

    Let's say that you have a service class, i.e. part of your BLL, and it has a dependency on a repository class, i.e. part of your DAL. If the service class creates an instance of the repository class internally then the two a tightly coupled. It's impossible to test the service class independently because, in order to create an instance of the service class, you must be able to create an instance of the repository class. If that repository gets its data from your database then it's impossible to test the service without having a live database. That means that you will always have to have the appropriate data in your database to fulfil your testing requirements and your tests will be slow because of the overhead of data access.

    By injecting an interface instead, you can create a mock during testing. Unlike a fake, a mock has no actual implementation. You just tell it that when some method or property is accessed on the interface then some result occurs, without ever having to write any code that creates that result. By using IoC you can specify how dependencies are implemented using configuration alone.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  5. #5

    Thread Starter
    PowerPoster
    Join Date
    Aug 2003
    Location
    Edinburgh, UK
    Posts
    2,773

    Re: Interfaces, DI/IoC, unit testing

    Thank you for that great explanation.
    So really what you are saying is that the above snip could be better improved where the BLL would get an interface returned from somewhere (i.e IoC approach) and use that instead, since you could swap in and out production DAL with a Test DAL where the Test DAL would be mocked correct?

    MVP 2007-2010 any chance of a regain?
    Professional Software Developer and Infrastructure Engineer.

  6. #6
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: Interfaces, DI/IoC, unit testing

    Correct
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  7. #7

    Thread Starter
    PowerPoster
    Join Date
    Aug 2003
    Location
    Edinburgh, UK
    Posts
    2,773

    Re: Interfaces, DI/IoC, unit testing

    ok, so what/how is the best way to implement this pattern/style? What I mean is, instead of the UI doing this:

    this.mMyBLL = new MyBusinessLogic();

    where mMyBLL is IBusinessLogic

    how can I then get it to automatically obtain that so it is one less burden on the UI to determine which business logic class to use?
    same thing with the DAL and the BLL where the BLL needs to get an instance of a DAL?

    MVP 2007-2010 any chance of a regain?
    Professional Software Developer and Infrastructure Engineer.

  8. #8
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: Interfaces, DI/IoC, unit testing

    In my office we use Castle or Autofac for IoC. We prefer Autofac but have to use Castle for one of our main clients. You can implement dependency injection via the constructor using an IoC container, e.g.
    csharp Code:
    1. internal class SomePresentationClass
    2. {
    3.     private SomeServiceClass firstService;
    4.     private SomeOtherServiceClass secondService;
    5.  
    6.     public SomePresentationClass()
    7.         : this(IocContainer.Resolve<ISomeServiceClass>()), IocContainer.Resolve<ISomeOtherServiceClass>())
    8.     {}
    9.  
    10.     public SomePresentationClass(ISomeServiceClass firstService, ISomeOtherServiceClass secondService)
    11.     {
    12.         this.firstService = firstService;
    13.         this.secondService = secondService;
    14.     }
    15.  
    16.     // ...
    17.  
    18. }
    You can then call the first constructor to have the services generated by the IoC container or the second constructor to pass in a specific service implementation, e.g. a mock or fake.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  9. #9

    Thread Starter
    PowerPoster
    Join Date
    Aug 2003
    Location
    Edinburgh, UK
    Posts
    2,773

    Re: Interfaces, DI/IoC, unit testing

    Thank you.

    lets imagine a BLL scenario:

    public MyBLL()
    {

    }


    BLL needs DAL right?
    IMO, the UI should never see a BLL have an overload of a constructor which accepts a DAL interface - I dont want the UI to see the overloads and want it restrictive where the UI shouldnt need to know, nor care about which BLL to instantiate and pass into the overload.

    how would I take care of this when it comes to testing?

    would the test project have the config file which would have the settings for injection/resolution?

    MVP 2007-2010 any chance of a regain?
    Professional Software Developer and Infrastructure Engineer.

  10. #10
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: Interfaces, DI/IoC, unit testing

    All your presentation class sees is the service interface, so it has no idea what constructors your service class may have. It doesn't care about constructors because it doesn't create the instances. It simply specifies what interface it wants to use and lets the IoC container take care of the rest.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  11. #11

    Thread Starter
    PowerPoster
    Join Date
    Aug 2003
    Location
    Edinburgh, UK
    Posts
    2,773

    Re: Interfaces, DI/IoC, unit testing

    I see..... Thanks!

    MVP 2007-2010 any chance of a regain?
    Professional Software Developer and Infrastructure Engineer.

  12. #12
    PowerPoster Evil_Giraffe's Avatar
    Join Date
    Aug 2002
    Location
    Suffolk, UK
    Posts
    2,555

    Re: Interfaces, DI/IoC, unit testing

    I would avoid the constructor overloads and only have the constructor that takes the dependencies as parameters. The problem with the no-arg overload is that you're then coupling all your classes that implement this pattern to the container. Ideally, the class (and almost all of your application) doesn't know about the container, it just specifies what external dependencies it needs and does its thing.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width