Search code examples
c#asp.net-coreintegration-testingasp.net-core-webapi

Integration tests give compilation error CS0051


I'm using ASP.NET 6 Core and writing a basic integration test for a controller that uses a mocked DBContext. Trying to base it on the Microsoft docs. But I can't build because I'm getting

CS0051 Inconsistent accessibility: parameter type 'CustomWebApplicationFactory<Program>' is less accessible than method 'ProjectsControllerTests.ProjectsControllerTests(CustomWebApplicationFactory<Program>)' DatabaseManagerService

But they are both public?!

ProjectControllersTests.cs

public class ProjectsControllerTests
    {
        private readonly CustomWebApplicationFactory<Program> _factory;
        private const string s_apiBaseUri = "/api/v1";

        public ProjectsControllerTests(CustomWebApplicationFactory<Program> factory)
        {
            // Arrange
            _factory = factory;
        }

        [Fact]
        public async Task Post_Responds201IfAuthenticatedAndRequiredFields_SuccessAsync()
        {
            // Arrange
            HttpClient? client = _factory.CreateClient(new WebApplicationFactoryClientOptions()
            {
                AllowAutoRedirect = false
            });

            var project = new Project() { Name = "Test Project" };
            var httpContent = new StringContent(JsonSerializer.Serialize(project));

            // Act
            var response = await client.PostAsync($"{s_apiBaseUri}/projects", httpContent);

            // Assert
            Assert.Equal(System.Net.HttpStatusCode.Created, response.StatusCode);
        }
    }

CustomWebApplicationFactory.cs

public class CustomWebApplicationFactory<TStartup>
        : WebApplicationFactory<TStartup> where TStartup : class
    {
        protected override void ConfigureWebHost(IWebHostBuilder builder)
        {
            builder.ConfigureServices(services =>
            {
                var descriptor = services.SingleOrDefault(
                    d => d.ServiceType ==
                        typeof(DbContextOptions<myDbContext>));

                if (descriptor != null)
                    services.Remove(descriptor);

                services.AddDbContext<myDbContext>(options =>
                {
                    options.UseInMemoryDatabase("InMemoryDbForTesting");
                });

                services.AddAuthentication("Test")
                .AddScheme<AuthenticationSchemeOptions, MockAuthHandler>(
                    "Test", options => { });

                var sp = services.BuildServiceProvider();

                using (var scope = sp.CreateScope())
                {
                    var scopedServices = scope.ServiceProvider;
                    var db = scopedServices.GetRequiredService<myDbContext>();
                    var logger = scopedServices
                        .GetRequiredService<ILogger<CustomWebApplicationFactory<Program>>>();

                    db.Database.EnsureCreated();

                    try
                    {
                        db.EndUsers.Add(new DataAccessLibrary.Models.EndUser() { ObjectIdentifier = "test-oid" });
                        db.SaveChanges();
                    }
                    catch (Exception ex)
                    {
                        logger.LogError(ex, "An error occurred seeding the " +
                            "database with test messages. Error: {Message}", ex.Message);
                    }
                }
            });
        }
    }

Solution

  • The Program class is not public in ASP.NET 6 Core. As per https://learn.microsoft.com/en-us/aspnet/core/migration/50-to-60-samples?view=aspnetcore-6.0#twa you can make Program public by appending the following to Program.cs:

    public partial class Program { }
    

    It should also be noted that the above test class must be defined as:

    public class ProjectsControllerTests : IClassFixture<CustomWebApplicationFactory<Program>>
    

    for DI to work.