4

How do I conduct the Dependency Injection in Integration Test? Calling the departmentRepository or departmentAppService, is giving me null and error below.

public class DepartmentAppServiceTest
{
    public SharedServicesContext context;
    public IMapper mapper;
    public IRepository<Department, int> departmentRepository;
    public IDepartmentAppService departmentAppService;

    public DepartmentAppServiceTest()
    {
        ServiceCollection services = new ServiceCollection();
        services.AddTransient<IRepository<Department>, BaseRepository<Department>>();
        services.AddTransient<IDepartmentAppService, DepartmentAppService>();

debugging and setting breakpoints, both calling this repository or app service are null,

new method

 [Fact]
 var departmentDto = await departmentAppService.GetDepartmentById(2);

Constructors for App Service

DepartmentAppService(departmentRepository, mapper)
DepartmentRepository(dbcontext)

Error:

Message: System.NullReferenceException : Object reference not set to an instance of an object.

  • @Izzy I can run dependency injection in actual program but not xunit, your link is not related, and causing flag on question, thanks –  Jul 31 '19 at 08:29
  • Have a look **[here](https://stackoverflow.com/questions/20423714/mocking-using-moq-in-c-sharp)** – Izzy Jul 31 '19 at 08:30
  • by the way you can use this `services.AddTransient, BaseRepository<>>();` – OMANSAK Jul 31 '19 at 09:01
  • 1
    Possible duplicate of [Unit Testing IServiceCollection Registration](https://stackoverflow.com/questions/51180523/unit-testing-iservicecollection-registration), this depcits how to unit test with dependency injection – johnny 5 Jul 31 '19 at 13:56

3 Answers3

7

For our integration tests we programatically startup the application and use HttpClient to make calls against the API Endpoints. This way your app runs through the whole Startup process and dependency injection works like a charm.

Here is an Example of the Server Startup and client creation, it can be reused for multiple tests:

_server = new TestServer(new WebHostBuilder()
                .UseEnvironment("Testing")
                .UseContentRoot(applicationPath)
                .UseConfiguration(new ConfigurationBuilder()
                    .SetBasePath(applicationPath)
                    .AddJsonFile("appsettings.json")
                    .AddJsonFile("appsettings.Testing.json")
                    .Build()
                )
                .UseStartup<TestStartup>());
_client = _server.CreateClient();
// Act
var response = await _client.GetAsync("/");

// Assert
response.EnsureSuccessStatusCode();

It's also documented by microsoft like this with the HttpClient:
https://learn.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-2.2

Yush0
  • 1,547
  • 18
  • 22
  • hi @Yush0 can you review this question it is not working –  Aug 02 '19 at 16:29
  • Actually you can use the Startup class from the application being test (.UseStartup() instead of TestStartup) and then use the services like this: myService = _server.Services.GetRequiredService(); – Ewerton Aug 14 '20 at 13:32
  • @Ewertonews: Yes that works too. In my case I inherited with TestStartup from Startup to override some functions regarding authentication. – Yush0 Sep 14 '20 at 07:55
  • hm.. nice.. that is right. – Ewerton Sep 14 '20 at 13:46
2

If you use the departmentAppService local variable, that is null. Your object is in the container. You can retrieve that by calling the GetRequiredService or GetService method.

I used the ServiceCollection in a console app like this way.

IServiceCollection services = new ServiceCollection();

services.AddSingleton<IDepartmentAppService, DepartmentAppService>();

using (ServiceProvider serviceProvider = services.BuildServiceProvider())
{
  var departmentAppService = serviceProvider.GetRequiredService<IDepartmentAppService>();

  await departmentAppService.GetDepartmentById(2);
}

The thing which you should care, the test class is recreating for each test cases.

Balazs
  • 21
  • 3
  • thanks, this is in my fact class, so how would I separate? var departmentDto = await departmentAppService.GetDepartmentById(2); –  Jul 31 '19 at 09:19
  • also need way to declare this new DepartmentAppService(departmentRepository, mapper); , I'll update question –  Jul 31 '19 at 09:22
  • It depends on your needs. 1) In the constructor, you can create the container and retrieve the objects to initialize the local variables. 2) The IClassFixture is a useful feature to keep your variables (not losing them). 3) ... – Balazs Jul 31 '19 at 09:42
-4

Using Moq you'll be able to fake the depedencies then pass them into your service. For example, your test method could look like:

//arrange  
var company = new company() { company_name = "TCS" };  

var mockRepo = new Mock<ICompany>();  
mockRepo.Setup(x => x.InsertCompany(company)).Returns(true);  

var companyObject = new Company(mockRepo.Object);  
var retrnData = companyObject.InsertCompany(company)

This code snippet is taken from this article which I suggest you check out:

https://www.c-sharpcorner.com/UploadFile/dacca2/unit-test-using-mock-object-in-dependency-injection/

Will
  • 205
  • 1
  • 8
  • 1
    This is for unit testing, original question is regarding integration test. An integration test should go against a real database and return real data, not mocked. The idea is to test everything that would be executed when the line of code executes. – Nick Gallimore Jan 27 '20 at 19:33
  • Integration tests, not unit tests. – Federico R. Figueredo Nov 07 '22 at 13:07