how to unit test asp.net core application with constructor dependency injection

Your controllers in .net core have dependency injection in mind from the start, but this does not mean you are required to use a dependency injection container.

Given a simpler class like:

public class MyController : Controller
{

    private readonly IMyInterface _myInterface;

    public MyController(IMyInterface myInterface)
    {
        _myInterface = myInterface;
    }

    public JsonResult Get()
    {
        return Json(_myInterface.Get());
    }
}

public interface IMyInterface
{
    IEnumerable<MyObject> Get();
}

public class MyClass : IMyInterface
{
    public IEnumerable<MyObject> Get()
    {
        // implementation
    }
}

So in your app, you're using the dependency injection container in your startup.cs, which does nothing more than provide a concretion of MyClass to use when IMyInterface is encountered. This does not mean it is the only way of getting instances of MyController however.

In a unit testing scenario, you can (and should) provide your own implementation (or mock/stub/fake) of IMyInterface as so:

public class MyTestClass : IMyInterface
{
    public IEnumerable<MyObject> Get()
    {
        List<MyObject> list = new List<MyObject>();
        // populate list
        return list;
    }        
}

and in your test:

[TestClass]
public class MyControllerTests
{

    MyController _systemUnderTest;
    IMyInterface _myInterface;

    [TestInitialize]
    public void Setup()
    {
        _myInterface = new MyTestClass();
        _systemUnderTest = new MyController(_myInterface);
    }

}

So for the scope of unit testing MyController, the actual implementation of IMyInterface does not matter (and should not matter), only the interface itself matters. We have provided a "fake" implementation of IMyInterface through MyTestClass, but you could also do this with a mock like through Moq or RhinoMocks.

Bottom line, you do not actually need the dependency injection container to accomplish your tests, only a separate, controllable, implementation/mock/stub/fake of your tested classes dependencies.


Although @Kritner's answer is correct, I prefer the following for code integrity and better DI experience:

[TestClass]
public class MatchRepositoryTests
{
    private readonly IMatchRepository matchRepository;

    public MatchRepositoryTests()
    {
        var services = new ServiceCollection();
        services.AddTransient<IMatchRepository, MatchRepositoryStub>();

        var serviceProvider = services.BuildServiceProvider();

        matchRepository = serviceProvider.GetService<IMatchRepository>();
    }
}

A simple way, I wrote a generic dependency resolver helper class and then built the IWebHost in my unit test class.

Generic Dependency Resolver

        using Microsoft.AspNetCore.Hosting;
        using Microsoft.AspNetCore.Mvc;
        using Microsoft.Extensions.Configuration;
        using Microsoft.Extensions.DependencyInjection;
        using Microsoft.Extensions.Hosting;
        public class DependencyResolverHelper
        {
            private readonly IWebHost _webHost;
    
            /// <inheritdoc />
            public DependencyResolverHelper(IWebHost webHost) => _webHost = webHost;
    
            public T GetService<T>()
            {
                var serviceScope = _webHost.Services.CreateScope();
                var services = serviceScope.ServiceProvider;
                try
                {
                  var scopedService = services.GetRequiredService<T>();
                  return scopedService;
                }
                catch (Exception e)
                {
                   Console.WriteLine(e);
                   throw;
                }
            }
        }
    }

Unit Test Project:

      [TestFixture]
        public class DependencyResolverTests
        {
            private DependencyResolverHelper _serviceProvider;

            public DependencyResolverTests()
            {

                var webHost = WebHost.CreateDefaultBuilder()
                    .UseStartup<Startup>()
                    .Build();
                _serviceProvider = new DependencyResolverHelper(webHost);
            }
    
            [Test]
            public void Service_Should_Get_Resolved()
            {
                
                //Act
                var YourService = _serviceProvider.GetService<IYourService>();
    
                //Assert
                Assert.IsNotNull(YourService);
            }
    

        }