【问题标题】:running asp.net web api application in integration tests在集成测试中运行 asp.net web api 应用程序
【发布时间】:2022-01-14 04:30:13
【问题描述】:

我有一个运行良好的 asp.net 核心 web api 应用程序,如下所示:

class Program
{
    /// <summary>
    ///     Main method
    /// </summary>
    static void Main(string[] args)
    {        
        // pass this as a parameter to specify what database I will like to use
        Func<IServiceProvider, IMyDatabase> GetDatabaseFactory = provider =>
        {
            // used for testing purposes. In production I will use the real DB
            return new MyDummyDatabase();
        }

        // create on a method so that it can be unit tested
        WebApplication app = CreateMyAppWebApiApplication(GetDatabaseFactory);

        // run application
        app.Run();
    }   ​
}

这里是 CreateMyAppWebApiApplication 方法。

/* I removed a lot of stuff I just want to illustrate the idea. Moreover, I have hardocoded a lot of stuff for testing purposes. Once it works I will move it to a configuration file.*/

static WebApplication CreateMyAppWebApiApplication(StartAspDotNetParameters parameters)
{
       ​var builder = WebApplication.CreateBuilder();

       ​builder.WebHost.ConfigureKestrel(k =>
       ​{            
           ​var port = 8888;

           ​k.Listen(System.Net.IPAddress.Any, port, listenOptions =>
           ​{
               ​// Enable support for HTTP1 and HTTP2 (required if you want to host gRPC endpoints)
               ​listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
               ​listenOptions.UseHttps();
           ​});
       ​});

       ​
       ​#region Add IoC dependencies

       ​// .. code some dependencies I need for the controlers

       ​#endregion

       ​// add controllers
       ​var mvcBuilder = builder.Services.AddControllers();

       ​// serialize enums as string
       ​mvcBuilder.AddJsonOptions(opts =>
           ​opts.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter())
       ​);

       ​// Configure Swagger/OpenAPI. More info: https://aka.ms/aspnetcore/swashbuckle
       ​builder.Services.AddEndpointsApiExplorer();
       ​builder.Services.AddSwaggerGen(options =>
       ​{            
           ​// code to configure...

       ​});       

       ​WebApplication? app = builder.Build();

       ​#region Configure the HTTP request pipeline.

       // first middleware to intercept swagger.json file
       // I have hardocded the path for testing purposes
       app.Use(async (HttpContext context, Func<Task> next) =>
       {
            if (requestUrl.EndsWith("myapp-swagger.json"))
            {
                var content = File.ReadAllText(@"T:\repos\.....\myapp-swagger.json.json");

                context.Response.ContentLength = content.Length;
                context.Response.ContentType = "application/json";
                await context.Response.WriteAsync(content);

                return;
            }
            else
            {
                // else execute next middleware
                await next();
            }

        });

       
              ​
       ​// enable swagger
       ​app.UseSwagger();

       ​// change swager endpoint
       ​app.UseSwaggerUI(c =>
       ​{
           ​c.RoutePrefix = "documentation";
           ​c.SwaggerEndpoint("/myapp-swagger.json", "MY API");            
       ​});
       ​app.UseHttpsRedirection();
       ​app.UseAuthorization();
       ​app.MapControllers();
       ​
       ​// This will run the application
       ​//// execute endpoint
       ​//app.Run();

       ​return app;

       ​#endregion
}

有关此方法的重要注意事项是:

​// I changed swagger default endpoint

    app.UseSwaggerUI(c =>
    {
           ​c.RoutePrefix = "documentation";
           ​c.SwaggerEndpoint("/myapp-swagger.json", "MY API");            
    });

// AND
       // first middleware to intercept swagger.json file
       // I have hardocded the path for testing purposes
       app.Use(async (HttpContext context, Func<Task> next) =>
       {
            if (requestUrl.EndsWith("myapp-swagger.json"))
            {
                var content = File.ReadAllText(@"T:\repos\.....\myapp-swagger.json.json");


                context.Response.ContentLength = content.Length;
                context.Response.ContentType = "application/json";
                await context.Response.WriteAsync(content);

                return;
            }
            else
            {
                // else execute next middleware
                await next();
            }

        });

不管怎样,这段代码都很好用。


现在问题来了:

当我尝试从这样的测试项目中运行相同的代码时:

[Fact]
public async Task TestUserPermissions_IntegrationTest()
{
        
        // pass the same dummyDatabase
        WebApplication app = CreateMyAppWebApiApplication(provider =>
        {
            // used for testing purposes. In production I will use the real DB
            return new MyDummyDatabase();
        });

        loginWorked = false;

        var taskLogin = Task.Run(async () =>
        {
            // make sure app starts by waiting 5 seconds
            await Task.Delay(5000);

            using var client = new HttpClient();

            var json = @"{ 'username':'tono', 'password':'myPassword'}".Replace("'", "\"");

            var content = new StringContent(json, Encoding.UTF8, "application/json");
            var result = await client.PostAsync("https://localhost:8888/api/LoginController/Login", content);


            Console.WriteLine(result.StatusCode);

            loginWorked = result.StatusCode == 200;            

        });

        // run application
        app.Run();

        await taskLogin ;

        Assert.True(loginWorked);
}

应用程序运行,但在测试项目中运行时我无法使用 API

【问题讨论】:

    标签: c# asp.net-core swagger


    【解决方案1】:

    终于找到答案了。因为我从不同的程序集运行项目,所以找不到控制器。这个 stackoverflow 解决方案使我的测试通过:

    https://stackoverflow.com/a/59121354/637142

    换句话说,我最终添加了这段代码

    // add controllers
    var mvcBuilder = builder.Services.AddControllers();
    
    // add controllers from this assembly. This is needed in case we are calling this method from unit tests project.
    mvcBuilder.PartManager.ApplicationParts.Add(new AssemblyPart(typeof(MyCustomController).Assembly));
    

    【讨论】:

      猜你喜欢
      • 2019-02-20
      • 2010-11-21
      • 1970-01-01
      • 2014-04-30
      • 1970-01-01
      • 2016-03-13
      • 2013-10-05
      • 1970-01-01
      • 2014-02-15
      相关资源
      最近更新 更多