gpt4 book ai didi

testing - XUnit DI 通过覆盖启动文件(.net 核心)

转载 作者:行者123 更新时间:2023-11-28 19:51:36 25 4
gpt4 key购买 nike

我已经构建了一个 WebAPI,除了我在 Postman 上运行的测试之外,我还想实现一些集成/单元测试。

现在我的业务逻辑非常薄,大部分时间更多的是 CRUD 操作,因此我想从测试我的 Controller 开始。

我有一个基本设置。存储库模式(接口(interface))、服务(业务逻辑)和 Controller 。流程是 Controller (DI Service) -> Service (DI Repo) -> Repo Action!

所以我所做的是覆盖我的启动文件以更改为内存数据库,其余的应该没问题(我假设)添加了服务,添加了存储库,现在我指向一个内存数据库,这很好用于我的基本测试。

namespace API.UnitTests
{
public class TestStartup : Startup
{
public TestStartup(IHostingEnvironment env)
: base(env)
{

}

public void ConfigureTestServices(IServiceCollection services)
{
base.ConfigureServices(services);
//services.Replace<IService, IMockedService>();
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
base.Configure(app, env, loggerFactory);
}

public override void SetUpDataBase(IServiceCollection services)
{
var connectionStringBuilder = new SqliteConnectionStringBuilder { DataSource = ":memory:" };
var connectionString = connectionStringBuilder.ToString();
var connection = new SqliteConnection(connectionString);

services
.AddEntityFrameworkSqlite()
.AddDbContext<ApplicationDbContext>(
options => options.UseSqlite(connection)
);
}
}
}

我写了第一个测试,但是 DatasourceService 不存在:

The following constructor parameters did not have matching fixture data: DatasourceService datasourceService

namespace API.UnitTests
{
public class DatasourceControllerTest
{
private readonly DatasourceService _datasourceService;

public DatasourceControllerTest(DatasourceService datasourceService)
{
_datasourceService = datasourceService;
}

[Xunit.Theory,
InlineData(1)]
public void GetAll(int companyFk) {
Assert.NotEmpty(_datasourceService.GetAll(companyFk));
}
}
}

我错过了什么?

最佳答案

你不能在测试类上使用依赖注入(inject)。您只能让 xunit 通过构造函数注入(inject)特殊的固定装置(参见 docs )。

对于集成测试,您希望使用 Microsoft.AspNetCore.TestHost 包中的 TestServer 类和一个单独的 Startup.cs 类(更容易设置配置而不是继承恕我直言)。

public class TestStartup : Startup
{
public TestStartup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}

public IConfigurationRoot Configuration { get; }

public void ConfigureTestServices(IServiceCollection services)
{
services.Replace(ServiceDescriptor.Scoped<IService, MockedService>());
services.AddEntityFrameworkSqlite()
.AddDbContext<ApplicationDbContext>(
options => options.UseSqlite(connection)
);
}

public void Configure(IApplicationBuilder app)
{
// your usual registrations there
}
}

在您的单元测试项目中,您需要创建一个TestServer 实例并执行测试。

public class DatasourceControllerTest
{
private readonly TestServer _server;
private readonly HttpClient _client;

public DatasourceControllerTest()
{
// Arrange
_server = new TestServer(new WebHostBuilder()
.UseStartup<TestStartup>());
_client = _server.CreateClient();
}

[Xunit.Theory,
InlineData(1)]
public async Task GetAll(int companyFk) {
// Act
var response = await _client.GetAsync($"/api/datasource/{companyFk}");
// expected result from rest service
var expected = @"[{""data"":""value1"", ""data2"":""value2""}]";

// Assert
// This makes sure, you return a success http code back in case of 4xx status codes
// or exceptions (5xx codes) it throws an exception
response.EnsureSuccessStatusCode();

var resultString = await response.Content.ReadAsStringAsync();
Assert.Equals(resultString, expectedString);
}
}

现在,当你调用写入数据库的操作时,你还可以检查数据是否真的写入了数据库:

[Xunit.Theory,
InlineData(1)]
public async Task GetAll(int companyFk) {
// Act
var response = await _client.DeleteAsync($"/api/datasource/{companyFk}");
// expected result from rest service

// Assert
response.EnsureSuccessStatusCode();

// now check if its really gone in the database. For this you need an instance
// of the in memory Sqlite DB. TestServer has a property Host, which is an IWebHost
// and it has a property Services which is the IoC container

var provider = _server.Host.Services;
var dbContext = provider.GetRequiredService<ApplicationDbContext>();

var result = await dbContext.YourTable.Where(entity => entity.Id == companyFk).Any();

// if it was deleted, the query should result in false
Assert.False(result);
}

关于testing - XUnit DI 通过覆盖启动文件(.net 核心),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41349140/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com