简体   繁体   English

.NET Core的NUnit Entity Framework集成测试依赖项注入问题

[英]NUnit Entity Framework integration test dependency injection issue with .NET Core

I have just started looking into .NET Core with Entity Framework. 我刚刚开始研究带有实体框架的.NET Core。 I have previously used .NET Framework with Ninject but I'm now trying to use the DI built into .NET Core. 我以前将.NET Framework与Ninject一起使用,但现在尝试使用.NET Core中内置的DI。

I have a TestBase class which my tests will derive from. 我有一个TestBase类,我的测试将源自该类。 I want this class to be responsible for creating and deleting a test database using [OneTimeSetUp] and [OneTimeTearDown] . 我希望此类负责使用[OneTimeSetUp][OneTimeTearDown]创建和删除测试数据库。 The problem is that I don't seem to be able to figure out how to gain access to my DI services in the setup and teardown methods. 问题是我似乎无法弄清楚如何在设置和拆卸方法中访问我的DI服务。 These methods cannot have parameters and my TestBase class must have a parameterless constructor so I can't get them from there either. 这些方法不能具有参数,而我的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();
    }
}

The above gives the following error: 上面给出了以下错误:

TestBase does not have a default constructor. TestBase没有默认的构造函数。

I may well be going about this the wrong way but this is how I've always done things in the past so please let me know if there is a better method when using .NET Core DI. 我可能会以错误的方式进行操作,但这是我过去一直做的事情,因此,请让我知道使用.NET Core DI时是否有更好的方法。


Startup class for reference: 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>());
    }
}

Thanks to NightOwl for pointing me in the right direction. 感谢NightOwl为我指出正确的方向。 A combination of the Microsoft article on integration testing and the possible dupe question led me to the following solution. 结合有关集成测试的Microsoft 文章和可能存在的重复问题,我找到了以下解决方案。

By using the TestServer from Microsoft.AspNetCore.TestHost I am able to access the DI ServiceProvider built in Startup . 通过使用Microsoft.AspNetCore.TestHostTestServer ,我可以访问Startup内置的DI ServiceProvider

TestBase: 测试库:

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();
    }
}

Startup: 启动:

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>());
    }
}

Integration testing ASP.NET Core is well covered by the Microsoft documentation. 集成测试ASP.NET Core已在Microsoft文档中很好地介绍了。

Basically, you need to install the Test Host project from NuGet Microsoft.AspNetCore.TestHost , then use it to launch the web environment within NUnit. 基本上,您需要从NuGet Microsoft.AspNetCore.TestHost安装Test Host项目,然后使用它在NUnit中启动Web环境。

Basic Example 基本范例

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);
    }
}

With the TestServer it is possible to intervene with the DI configuration and/or the IConfiguration to substitute fakes in the configuration. 使用TestServer可以干预DI配置和/或IConfiguration来替代配置中的伪造品。 See Reconfigure dependencies when Integration testing ASP.NET Core Web API and EF Core . 在集成测试ASP.NET Core Web API和EF Core时,请参阅重新配置依赖项

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM