NUnit 实体框架集成测试依赖项注入问题与 .NET Core



我刚刚开始使用实体框架研究.NET Core。我以前使用过带有Ninject的.NET Framework,但现在我正在尝试使用.NET Core中内置的DI。

我有一个TestBase类,我的测试将从中派生。我希望这个类负责使用 [OneTimeSetUp][OneTimeTearDown] 创建和删除测试数据库。问题是我似乎无法弄清楚如何在设置和拆卸方法中访问我的 DI 服务。这些方法不能有参数,我的TestBase类必须有一个无参数构造函数,所以我也无法从那里获取它们。

[SetUpFixture]
public partial class TestBase
{
    protected IEFDatabaseContext DataContext { get; set; }
    public TestBase(IEFDatabaseContext dataContext)
    {
        this.DataContext = dataContext;
    }
    [OneTimeSetUp]
    public void TestInitialise()
    {
        this.DataContext.Database.EnsureCreated();
    }
    [OneTimeTearDown]
    public void TestTearDown()
    {
        this.DataContext.Database.EnsureDeleted();
    }
}

上面给出了以下错误:

TestBase没有默认构造函数。

很可能以错误的方式解决这个问题,但这就是我过去一直做事的方式,所以请在使用 .NET Core DI 时让我知道是否有更好的方法。


Startup类供参考:

public class Startup
{
    private readonly IConfiguration config;
    public Startup(IConfiguration config)
    {
        this.config = config;
    }
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<TestDataContext>(
            options => options.UseSqlServer(this.config.GetConnectionString("TestConnectionString")),
            ServiceLifetime.Singleton);
        services.AddScoped<IEFDatabaseContext>(provider => provider.GetService<TestDataContext>());
    }
}

感謝NightOwl為我指出了正確的方向。Microsoft篇关于集成测试的文章和可能的欺骗问题相结合,使我得出了以下解决方案。

通过使用Microsoft.AspNetCore.TestHost TestServer,我能够访问Startup内置的DI ServiceProvider

测试库:

public partial class TestBase
{
    protected readonly TestServer server;
    protected readonly IEFDatabaseContext DataContext;
    public TestBase()
    {
        this.server = new TestServer(new WebHostBuilder().UseStartup<Startup>());
        this.DataContext = this.server.Host.Services.GetService<IEFDatabaseContext>();
    }
    [OneTimeSetUp]
    public void TestInitialise()
    {
        this.DataContext.Database.EnsureCreated();
    }
    [OneTimeTearDown]
    public void TestTearDown()
    {
        this.DataContext.Database.EnsureDeleted();
    }
}

启动:

public class Startup
{
    private readonly IConfiguration config;
    public Startup(IConfiguration config)
    {
        this.config = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json")
            .Build();
    }
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
    }
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<TestDataContext>(
            options => options.UseSqlServer(this.config.GetConnectionString("TestConnectionString")),
            ServiceLifetime.Singleton);
        services.AddScoped<IEFDatabaseContext>(provider => provider.GetService<TestDataContext>());
    }
}

Core ASP.NET 集成测试在Microsoft文档中得到了很好的介绍。

基本上,您需要从 NuGet Microsoft.AspNetCore.TestHost 安装测试主机项目,然后使用它在 NUnit 中启动 Web 环境。

基本示例

public class TestClass
{
    private TestServer _server;
    private HttpClient _client;
    [OneTimeSetUp]
    public void SetUp()
    {
        // Arrange
        _server = new TestServer(new WebHostBuilder()
            .UseStartup<Startup>());
        _client = _server.CreateClient();
    }
    [OneTimeTearDown]
    public void TearDown()
    {
        _server = null;
        _client = null;
    }
    [Test]
    public async Task ReturnHelloWorld()
    {
        // Act
        var response = await _client.GetAsync("/");
        response.EnsureSuccessStatusCode();
        var responseString = await response.Content.ReadAsStringAsync();
        // Assert
        Assert.Equal("Hello World!",
            responseString);
    }
}

使用TestServer可以干预DI配置和/或IConfiguration以替换配置中的假货。请参阅在核心 Web API 和 EF Core 进行集成测试时重新配置依赖项 ASP.NET。

最新更新