其他。您实际执行的操作取决于您测试的内容、您想要配置的内容以及您的个人偏好。在这种情况下,虽然唯一可以抽象的是对CreateClient 或CreateDefaultClient 的调用,这并不多。也可能不需要缓存该实例。
许多测试会创建一个单独的 Application 类,该类继承自 WebApplicationFactory<>,允许您覆盖配置或添加可能有用的额外成员。
In these tests 例如,PlaygroundApplication 类用于设置环境并将配置的 DbContext 替换为使用内存中 SQLite 的 DbContext。该 repo 演示了 .NET 6 最小 API,因此它使用 Program 而不是 Startup,但这根本不会影响测试:
internal class PlaygroundApplication : WebApplicationFactory<Program>
{
private readonly string _environment;
public PlaygroundApplication(string environment = "Development")
{
_environment = environment;
}
protected override IHost CreateHost(IHostBuilder builder)
{
builder.UseEnvironment(_environment);
// Add mock/test services to the builder here
builder.ConfigureServices(services =>
{
services.AddScoped(sp =>
{
// Replace SQLite with in-memory database for tests
return new DbContextOptionsBuilder<TodoDb>()
.UseInMemoryDatabase("Tests")
.UseApplicationServiceProvider(sp)
.Options;
});
});
return base.CreateHost(builder);
}
}
这个类是used in tests directly。它甚至不被用作类夹具:
[Fact]
public async Task GET_Root_Responds_OK()
{
await using var application = new PlaygroundApplication();
using var client = application.CreateClient();
using var response = await client.GetAsync("/");
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("Hello World!", await response.Content.ReadAsStringAsync());
}
在那之后,这是一个风格和方便的问题。您可以:
- 具有单独配置的多个此类类。如果配置复杂和/或重复,例如针对不同的场景,并且您不想在配置中乱扔测试,则很有用。
- 通过构造函数选项参数化的单个。如果选项很少,则很有用。如果选项太多,则可能是时候将其拆分为单独的类了。配置一个超灵活的类可能比创建几个不同的特殊类型更麻烦
-
TestApplication 基类,具有通用配置和适用于多种场景的专用派生类。
所有选项都可以用作固定装置。您可以将这些选项中的任何一个与Theory 结合使用,以使用不同的配置运行相同的测试。