How to test database actions in asp.net core integration test?

asp.net-core dependency-injection entity-framework-core integration-testing

Question

I am trying to integration test my app.

for example, in my AbController I have PostAb(AbDTO abDTO) method, and I want to test that calling this method will add abDTO to db.

now my test setup:

    [SetUp]
    public void SetUp()
    {
        _server = new TestServer(new WebHostBuilder()
            .UseEnvironment("testing")
            .UseStartup<Startup>());

        _client = _server.CreateClient();
    }

and my test should look like:

    [Test]
    public async Task PostAbSanity()
    {
        await _client.PostAsync("/rest/v1/Ab", new Ab{Id=1});
        _context.Abs.find(1).should().NotBeNull();
    }

but, how can I inject _context into test? in my app I inject it through constructors, but in tests I cant.

thanks!

1
0
12/8/2016 11:02:58 PM

Popular Answer

While I will concede that integration testing with an in-memory database is the most thorough and safe way to work, my specific situation would make this aspect extremely difficult and time consuming. I am using a hosted SQL development server that I overwrite after a period of tests. I worked for several days and found the below to be the process that gave me the results I was looking for.

  • DotNet Core 2.1
  • Hexagonal (Onion) architecture needing to test the business logic written in my Data Access Layer

Program.CS file I added:

//for integration testing
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
    .ConfigureServices(services => services.AddAutofac())
    .UseStartup<Startup>();

My Integration Test File:

using Core.Data.Entities.Model;
using Core.Data.Entities.UTIA;
using FluentAssertions;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.EntityFrameworkCore;
using Profile.Data.Repos;
using Profile.Domain.DomainObjects;
using Super2.Web;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Xunit;

namespace Profile.Test
{
    public class EmployeeProfileIntegrationTest : IClassFixture<WebApplicationFactory<Startup>>
    {
        private readonly HttpClient _client;

        public EmployeeProfileIntegrationTest(WebApplicationFactory<Startup> factory)
        {
            _client = factory.CreateClient();

        }

        private DBContext GetContext()
        {
            var options = new DbContextOptionsBuilder<DBContext>()
                .UseSqlServer("Server = 'Connection String from appsettings'")
                .Options;

            var context = new DBContext(options);
            return context;
        }



        [Fact]
        public async Task TestChildProtectionEmployeeGetData()
        {
            //Arrange
            var ApplicationUserId = XXXX;
            var repo = new EmployeeProfileRepo(GetContext());

            //ACT
            var sut = await repo.GetChildProtectionHistory(ApplicationUserId);

            //Assert
            var okResult = sut.Should().BeOfType<List<DomainObject>>().Subject;
            okResult.First().ApplicationUserId.Should().Be(XXXX);
        }
    }
}

While I am injecting my context into a different layer, I would suspect that it would work the same for a controller. I included the startup snippet as this caused me some issues as the testserver was looking for IWebHostBuilder instead of the default Core2.1 IWebHost.

Either way, this worked for me. Hope you can get some help from this.

1
12/20/2018 1:15:21 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow