locked
DI Container RRS feed

  • Question

  • User-305496339 posted

    Hi Friends,

    I was wondering is there a rule of thumb or best practice for using DI containers. Or how do I know when i really need to use this framework? Thanks !

    Friday, June 14, 2019 8:16 PM

Answers

  • User-821857111 posted

    The main use of a DI container is to detach classes from concrete dependencies. This is particularly useful for automated unit testing. 

    Let's say that you have an MVC action method that relies on a class (GMailer) to send an email.  The mailer class connects to Gmail and does its thing when its SendEmail method is called. All you want to test is that the action method actually calls the SendEmail method. At the moment, when you instantiate the controller in your unit test and invoke the action method, the GMailer class will actually try to send an email, resulting in a relatively slow test, which may fail because the GMailer class (which you aren't testing) cannot connect to Gmail for some reason.

    So what you do instead is pass an abstraction to the method (usually an interface) representing the mailer class:

    public interface IMailer
    {
        void SendMail(MailMessage msg);
    }

    In your application, you use a DI container to register the concrete type that this interface should resolve to at runtime:

    services.AddTransient<IMailer, GMailer>();  // ASP.NET Core DI

    or

    container.Bind<IMailer>().To<GMailer>(); // Ninject example

    But in your test project, you register a fake or mock type instead, which has a SendMail method that doesn't do anything at all.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, June 18, 2019 12:11 PM
  • User753101303 posted

    Hi,

    And more generally any case where swapping to some other implementation could help such as :
    - have an app that uses distinct implementations depending on where it runs (such as sending mails or storing files differently depending on running on premise or in the cloud)
    - replacing a current service with a brand new implementation at any time and still being able to revert back to the old implementation (for example an Excel export service using interop to another using the Open XML SDK)
    - and likely others...

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, June 18, 2019 12:47 PM

All replies

  • User-821857111 posted

    The main use of a DI container is to detach classes from concrete dependencies. This is particularly useful for automated unit testing. 

    Let's say that you have an MVC action method that relies on a class (GMailer) to send an email.  The mailer class connects to Gmail and does its thing when its SendEmail method is called. All you want to test is that the action method actually calls the SendEmail method. At the moment, when you instantiate the controller in your unit test and invoke the action method, the GMailer class will actually try to send an email, resulting in a relatively slow test, which may fail because the GMailer class (which you aren't testing) cannot connect to Gmail for some reason.

    So what you do instead is pass an abstraction to the method (usually an interface) representing the mailer class:

    public interface IMailer
    {
        void SendMail(MailMessage msg);
    }

    In your application, you use a DI container to register the concrete type that this interface should resolve to at runtime:

    services.AddTransient<IMailer, GMailer>();  // ASP.NET Core DI

    or

    container.Bind<IMailer>().To<GMailer>(); // Ninject example

    But in your test project, you register a fake or mock type instead, which has a SendMail method that doesn't do anything at all.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, June 18, 2019 12:11 PM
  • User753101303 posted

    Hi,

    And more generally any case where swapping to some other implementation could help such as :
    - have an app that uses distinct implementations depending on where it runs (such as sending mails or storing files differently depending on running on premise or in the cloud)
    - replacing a current service with a brand new implementation at any time and still being able to revert back to the old implementation (for example an Excel export service using interop to another using the Open XML SDK)
    - and likely others...

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, June 18, 2019 12:47 PM