HttpClient GET returns 404 未找到
HttpClient GET returns 404 not found
我正在尝试 运行 在一个简单的控制器上进行集成测试,该控制器 returns 来自 entity framework 的数据。我已经编写了单元测试并且所有工作都按预期进行。
我已经连接了 xUnit 集成测试,但是当我 运行 一个简单的 Get 到我的控制器时,我得到一个 404 not found。如果我在浏览器中启动项目并 运行 通过邮递员获取,我会正确点击控制器并执行操作。
我的 xUnit TestFixture Class
public sealed class TestFixture<TStartup> : IDisposable where TStartup : class
{
public readonly TestServer Server;
public readonly HttpClient Client;
public TestFixture()
{
var builder = BuildWebHost();
Server = new TestServer(builder);
Client = Server.CreateClient();
}
public static IWebHostBuilder BuildWebHost()
{
var host = new WebHostBuilder()
.UseStartup<TestStartup>()
.ConfigureAppConfiguration((hostContext, config) =>
{
config.Sources.Clear();
config.SetBasePath(Directory.GetCurrentDirectory());
config.AddJsonFile("appsettings.test.json", optional: true, reloadOnChange: true);
});
return host;
}
}
我的控制器测试class
public class FlowApiControllerTests : IClassFixture<TestFixture<Startup>>
{
private readonly HttpClient _httpClient;
public FlowApiControllerTests(TestFixture<Startup> fixture)
{
_httpClient = fixture.Client;
}
[Fact]
public async Task Get_FlowApiTest()
{
var response = await _httpClient.GetAsync("/flowapi");
response.StatusCode.Should().Be(HttpStatusCode.OK);
var content = await response.Content.ReadAsStringAsync();
var model = JsonConvert.DeserializeObject<List<FlowApi>>(content);
model.Count.Should().Be(2);
}
}
最后是我的控制器
[Route("[controller]")]
[ApiController]
public class FlowApiController : ControllerBase
{
private readonly IFlowApiRepository _repository;
public FlowApiController(IFlowApiRepository repository)
{
_repository = repository;
}
// GET: api/FlowApi
[HttpGet]
public async Task<IActionResult> Get()
{
var result = await _repository.Select<FlowApi>();
return Ok(result);
}
}
我不明白为什么我在测试中没有点击控制器,但可以从邮递员那里点击它。
感谢@Ajeet Kumar 为我指明了 WebApplicationFactory 的方向,我采用了 the ASP.NET Core Integration Test docs 中的方法,并修改了我的 TestFixture class 以反映该方法。我还导入了 nuget 包 Microsoft.AspNetCore.Mvc.Testing。我的 TestFixture class 现在看起来像
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureServices(services =>
{
var descriptor = services.SingleOrDefault(d => d.ServiceType == typeof(DbContextOptions<ApiContext>));
if (descriptor != null)
{
services.Remove(descriptor);
}
// Add ApplicationDbContext using an in-memory database for testing.
services.AddDbContext<ApiContext>((options, context) =>
{
context.UseInMemoryDatabase("InMemoryDbForTesting");
});
services.AddTransient<DatabaseSeeder>();
// Build the service provider.
var sp = services.BuildServiceProvider();
using (var scope = sp.CreateScope())
{
var scopedServices = scope.ServiceProvider;
var db = scopedServices.GetRequiredService<ApiContext>();
// Ensure the database is created.
db.Database.EnsureCreated();
try
{
// Seed the database with test data.
var seeder = scopedServices.GetService<DatabaseSeeder>();
seeder.SeedFlowApplicationData().Wait();
我正在尝试 运行 在一个简单的控制器上进行集成测试,该控制器 returns 来自 entity framework 的数据。我已经编写了单元测试并且所有工作都按预期进行。
我已经连接了 xUnit 集成测试,但是当我 运行 一个简单的 Get 到我的控制器时,我得到一个 404 not found。如果我在浏览器中启动项目并 运行 通过邮递员获取,我会正确点击控制器并执行操作。
我的 xUnit TestFixture Class
public sealed class TestFixture<TStartup> : IDisposable where TStartup : class
{
public readonly TestServer Server;
public readonly HttpClient Client;
public TestFixture()
{
var builder = BuildWebHost();
Server = new TestServer(builder);
Client = Server.CreateClient();
}
public static IWebHostBuilder BuildWebHost()
{
var host = new WebHostBuilder()
.UseStartup<TestStartup>()
.ConfigureAppConfiguration((hostContext, config) =>
{
config.Sources.Clear();
config.SetBasePath(Directory.GetCurrentDirectory());
config.AddJsonFile("appsettings.test.json", optional: true, reloadOnChange: true);
});
return host;
}
}
我的控制器测试class
public class FlowApiControllerTests : IClassFixture<TestFixture<Startup>>
{
private readonly HttpClient _httpClient;
public FlowApiControllerTests(TestFixture<Startup> fixture)
{
_httpClient = fixture.Client;
}
[Fact]
public async Task Get_FlowApiTest()
{
var response = await _httpClient.GetAsync("/flowapi");
response.StatusCode.Should().Be(HttpStatusCode.OK);
var content = await response.Content.ReadAsStringAsync();
var model = JsonConvert.DeserializeObject<List<FlowApi>>(content);
model.Count.Should().Be(2);
}
}
最后是我的控制器
[Route("[controller]")]
[ApiController]
public class FlowApiController : ControllerBase
{
private readonly IFlowApiRepository _repository;
public FlowApiController(IFlowApiRepository repository)
{
_repository = repository;
}
// GET: api/FlowApi
[HttpGet]
public async Task<IActionResult> Get()
{
var result = await _repository.Select<FlowApi>();
return Ok(result);
}
}
我不明白为什么我在测试中没有点击控制器,但可以从邮递员那里点击它。
感谢@Ajeet Kumar 为我指明了 WebApplicationFactory 的方向,我采用了 the ASP.NET Core Integration Test docs 中的方法,并修改了我的 TestFixture class 以反映该方法。我还导入了 nuget 包 Microsoft.AspNetCore.Mvc.Testing。我的 TestFixture class 现在看起来像
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureServices(services =>
{
var descriptor = services.SingleOrDefault(d => d.ServiceType == typeof(DbContextOptions<ApiContext>));
if (descriptor != null)
{
services.Remove(descriptor);
}
// Add ApplicationDbContext using an in-memory database for testing.
services.AddDbContext<ApiContext>((options, context) =>
{
context.UseInMemoryDatabase("InMemoryDbForTesting");
});
services.AddTransient<DatabaseSeeder>();
// Build the service provider.
var sp = services.BuildServiceProvider();
using (var scope = sp.CreateScope())
{
var scopedServices = scope.ServiceProvider;
var db = scopedServices.GetRequiredService<ApiContext>();
// Ensure the database is created.
db.Database.EnsureCreated();
try
{
// Seed the database with test data.
var seeder = scopedServices.GetService<DatabaseSeeder>();
seeder.SeedFlowApplicationData().Wait();