1

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!

12
  • I would suggest then that you do a get after the post to verify that posted record was created. Commented Dec 8, 2016 at 23:20
  • But not for all my post method exists the contrary get, and vice versa Commented Dec 8, 2016 at 23:24
  • and also I'm not sure It's good Idea, since instead the test will focus on it's method, it'll call also many other API for seeding the db etc. is this the normal way integration test should work? Commented Dec 8, 2016 at 23:26
  • Your last two comments were not clear. I didn't understand what you meant. Commented Dec 8, 2016 at 23:35
  • 1
    OK I understand what you mean now. point taken. Commented Dec 8, 2016 at 23:55

2 Answers 2

3

I'm assuming you are using SqlLite, so you can edit your SetUp method like this:

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

    _client = _server.CreateClient();

    var optionsBuilder = new DbContextOptionsBuilder<BloggingContext>();

    optionsBuilder.UseSqlite("Filename=./blog.db");

    _context = new BloggingContext(optionsBuilder.Options);
}

Please let me know if this is useful

Sign up to request clarification or add additional context in comments.

6 Comments

no, it's wont replace the _context which registered in startup.cs like: public void ConfigureServices(IServiceCollection services) { var connection = @"Server=(localdb)\mssqllocaldb;Database=EFGetStarted.AspNetCore.NewDb;Trusted_Connection=True;"; services.AddDbContext<BloggingContext>(options => options.UseSqlServer(connection)); see in first link
What are you using? Sql Server or SqlLite
in integration test I'm using sql server to be as most same to my real db as possible.
OK, I think there is a misunderstand about "injection" in unit tests, if you take a look on this tutorial: codeproject.com/articles/1112848/…, in unit tests there is a "mock" for DbContext, why do you want to make this for your case ?
I get your point, in that case the db context will be injected by web api project when you init the server in your SetUp method
|
1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.