我有一個運行良好的 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
uj5u.com熱心網友回復:
終于找到了答案。因為我從不同的程式集運行專案,所以找不到控制器。這個 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));
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/414095.html
標籤:
