Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dependency Injection resolve and unit testing

I'm trying to learn dependency injection and have come across a problem, when unit testing the application.

I'm writing a console application and the container is created and initialized in Main(), it's available as a get-property in Program.Container, so anywhere in my application I can call Program.Container.Resolve<..>().

I have a ServiceValidator class like this:

public class ServiceValidator
{
    private readonly IConfiguration _configuration;
    private readonly IService _service;

    public ServiceValidator(IConfiguration configuration, IService service)
    {
        _configuration = configuration;
        _service = service;
    }

In another class I use

ServiceValidator serviceValidator = Program.Container.Resolve<ServiceValidator>();
serviceValidator.VerifyVersion();

It's the call to Program.Container.Resolve that causes me problems in the unit test, as it hasn't been setup.

Is that a bad practice, to call resolve on the container? I could create the ServiceValidator instance in Main() and pass the object around, but that seems stupid as it would cause lots of parameters for the objects that are just passed around to the next method.

So I guess it's acceptable to call Resolve within a class, but then the container must be configured for the unit test. How should I do that, should I move the container to another place than the Program class? What would you recommend?

If it matters, I'm using Unity and C#

Thanks :-)

like image 949
Karsten Avatar asked May 04 '09 13:05

Karsten


People also ask

How does dependency injection help unit testing?

Dependency injection helps if you have a class that needs a dependent class-instance to do some sub-processing. Instead of DI you can seperate the logic of a business-method into a data-gethering-part (that is not unit-testable) and a calculation part that can be unit-tested.

How do you unit test a service with a dependency?

Angular services can be tested in a couple of different ways, two most prominent being isolated tests and using the Angular TestBed . However, things get interesting when the service under test has dependencies (injected using Angular's dependency injection).

What is difference between e2e and unit testing?

While both add value to the development process, they are different in many ways. End-to-end testing is a testing process in which the tester tests a software application from the user's perspective. Unit testing is a testing process where the developer verifies that individual units of source code work correctly.


1 Answers

Is that a bad practice, to call resolve on the container? I could create the ServiceValidator instance in Main() and pass the object around, but that seems stupid as it would cause lots of parameters for the objects that are just passed around to the next method.

When you use dependency injection all the way, then you won't need to pass lots of parameters to objects. The constructor of each object should have as parameters only those dependencies which it itself uses directly - it won't know about the transitive dependencies of its direct dependencies.

So if you have a class X which requires a ServiceValidator, then class X will have a constructor parameter of type ServiceValidator. Then if some class Y uses class X, then class Y will have a constructor parameter of type X. Notice that Y knows nothing about ServiceValidator, so you don't need to pass the ServiceValidator from one class to another - the only place where it is used is when constructing X, and that is often done by a DI framework or in only one place in a hand-written factory.

Some links for more information:

  • http://martinfowler.com/articles/injection.html
  • http://www.youtube.com/watch?v=RlfLCWKxHJ0 - your question about passing objects around is answered starting 19:20 "Myth about DI"
like image 189
Esko Luontola Avatar answered Sep 22 '22 03:09

Esko Luontola