Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET Core Testing - No method 'public static IHostBuilder CreateHostBuilder(string[] args)

I'm trying to setup my application in tests and use in Startup's Configure method context.Database.EnsureCreated() and expecting Sqlite file appear in Test's bin folder

Here's my code:

using Microsoft.AspNetCore.Mvc.Testing;
using System.Threading.Tasks;
using Xunit;

namespace MyApp.Tests
{
    public class UnitTest1 : IClassFixture<CustomWebApplicationFactory<FakeStartup>>
    {
        private readonly CustomWebApplicationFactory<FakeStartup> _factory;

        public UnitTest1(CustomWebApplicationFactory<FakeStartup> factory)
        {
            _factory = factory;
        }

        [Fact]
        public async Task Test1()
        {
            // Arrange
            var client = _factory.CreateClient();

            // Act
            var response = await client.GetAsync("https://localhost:5001/");

            // Assert
            response.EnsureSuccessStatusCode(); // Status Code 200-299
            Assert.Equal("text/html; charset=utf-8", response.Content.Headers.ContentType.ToString());
        }
    }
}

Which is using WebAppFactory:

using MyApp.Tests;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;

public class CustomWebApplicationFactory<TStartup> : WebApplicationFactory<TStartup> where TStartup : class
{
    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        builder.UseStartup<FakeStartup>();
    }
}

Where FakeStartup is:

using MyApp.Database;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;

namespace MyApp.Tests
{
    public class FakeStartup
    {
        public FakeStartup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {            
            services.AddControllers();

            services.AddDbContext<Context>(x => x.UseSqlite($"filename={Guid.NewGuid():N}.db"));

            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "Test API", Version = "v1" });
            });
        }
    }

    public static void Configure(IApplicationBuilder app, IWebHostEnvironment env, Context context)
    {
        context.Database.EnsureDeleted();
        context.Database.EnsureCreated();

        app.UseSwagger();
        app.UseSwaggerUI(c =>
        {
            c.SwaggerEndpoint("/swagger/v1/swagger.json", "Test API v1");
            c.RoutePrefix = string.Empty;
        });

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseForwardedHeaders(new ForwardedHeadersOptions
        {
            ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
        });

        app.UseAuthentication();

        app.UseCors(x =>
        {
            x.AllowAnyOrigin();
            x.AllowAnyMethod();
            x.AllowAnyHeader();
        });

        app.UseHttpsRedirection();

        app.UseRouting();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }
}

Here's problem

  Message: 
    System.InvalidOperationException : No method 'public static IHostBuilder CreateHostBuilder(string[] args)' or 'public static IWebHostBuilder CreateWebHostBuilder(string[] args)' found on 'AutoGeneratedProgram'. Alternatively, WebApplicationFactory`1 can be extended and 'CreateHostBuilder' or 'CreateWebHostBuilder' can be overridden to provide your own instance.
  Stack Trace: 
    WebApplicationFactory`1.CreateWebHostBuilder()
    WebApplicationFactory`1.EnsureServer()
    WebApplicationFactory`1.CreateDefaultClient(DelegatingHandler[] handlers)
    WebApplicationFactory`1.CreateDefaultClient(Uri baseAddress, DelegatingHandler[] handlers)
    WebApplicationFactory`1.CreateClient(WebApplicationFactoryClientOptions options)
    WebApplicationFactory`1.CreateClient()
    UnitTest1.Test1() line 20
    --- End of stack trace from previous location where exception was thrown

What may be causing this? thanks in advance

like image 602
tezzly Avatar asked Apr 11 '20 15:04

tezzly


People also ask

What is CreateHostBuilder in ASP.NET Core?

The host is typically configured, built, and run by code in the Program class. The Main method: Calls a CreateHostBuilder method to create and configure a builder object. Calls Build and Run methods on the builder object.

What is IHostBuilder in ASP.NET Core?

ConfigureAppConfiguration(IHostBuilder, Action<IConfigurationBuilder>) Sets up the configuration for the remainder of the build process and application. This can be called multiple times and the results will be additive. The results will be available at Configuration for subsequent operations, as well as in Services.

What is generic host and webhost in ASP.NET Core?

NET Core 2.2 use the Web Host for web application. The Generic host got included with ASP.NET CORE 2.1 and became the de-facto standard for the future version of . NET Core. Though the Generic host got included in . NET core 2.1 it was only used for non HTTP workloads.

What is .NET generic host?

The Generic Host can be used with other types of . NET applications, such as Console apps. A host is an object that encapsulates an app's resources and lifetime functionality, such as: Dependency injection (DI)


2 Answers

Updated with comment from CoreyP:

If you are getting this error and you're on .NET 6.0, you might need to update the Microsoft.AspNetCore.Mvc.Testing package, see this question: Integration test for ASP.NET Core 6 web API throws System.InvalidOperationException

Solution:

Create CustomWebApplicationFactory this way

public class CustomWebApplicationFactory<TStartup> : WebApplicationFactory<TStartup> where TStartup : class
{
    protected override IHostBuilder CreateHostBuilder()
    {
        var builder = Host.CreateDefaultBuilder()
                          .ConfigureWebHostDefaults(x =>
                          {
                              x.UseStartup<FakeStartup>().UseTestServer();
                          });
        return builder;
    }
}

Found here:

https://thecodebuzz.com/no-method-public-static-ihostbuilder-createhostbuilder/

like image 122
tezzly Avatar answered Oct 08 '22 14:10

tezzly


I was getting this error because I had not followed the MS prerequisites closely enough. In my case I had not updated the Project SDK in the test csproj file. It needs to be <Project Sdk="Microsoft.NET.Sdk.Web"> (note the '.Web' on the end).

like image 43
Rossco Avatar answered Oct 08 '22 14:10

Rossco