gpt4 book ai didi

c# - 在服务中注入(inject)模拟的 dbContext - 集成测试

转载 作者:行者123 更新时间:2023-11-28 21:03:27 24 4
gpt4 key购买 nike

我正在尝试实现集成测试,以便我可以仅使用 HttpClient 测试我的端点

public async Task TestEndPoint()
{
using (var response = await _client.GetAsync($"/api/car/{id}"))
{
//...
}
}

我正在使用 Fixture 类来帮助我解决这个问题

private readonly TestServer _server;
public Fixture()
{
var dbContextOptions = new DbContextOptionsBuilder<CarDbContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.Options;

var mockContext = new Mock<CarDbContext>(dbContextOptions);
var mockOwnerSet = new Mock<DbSet<Owner>>();
var mockCarSet = new Mock<DbSet<Car>>();
mockContext.Setup(m => m.Owners).Returns(mockOwnerSet.Object);
mockContext.Setup(m => m.Cars).Returns(mockCarSet.Object);

var carService = new CarService(mockContext.Object);

_server = new TestServer(new WebHostBuilder()
.ConfigureAppConfiguration((context, conf) =>
{
conf.AddJsonFile(@Directory.GetCurrentDirectory() + "../appsettings.json");
}).UseStartup<Startup>()
.ConfigureServices(services =>
{
services.AddDbContext<CarDbContext>(options => options.UseInMemoryDatabase("Test"));
services.AddScoped<ICarService>(_ => carService);
})
);

Client = _server.CreateClient();
}

在 Startup.cs 内部

public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<CarDbContext>(options => { options.UseSqlServer(Configuration.GetConnectionString("Db")); });
services.AddTransient<ICarService, CarService>();
}
}

服务等级

public class CarService: ICarService {
private readonly CarDbContext _carDbContext;

public CarService(CarDbContext carDbContext)
{
_carDbContext = carDbContext;
}

public async Task<Car> GetAsync(int id)
{
return await _carDbContext.Cars.FindAsync(id); //this always returns null
}
}

我的问题是:为什么模拟数据库上下文没有在 CarService 中使用

return await _carDbContext.Cars.FindAsync(id); always returns null

更新:

private readonly TestServer _server;
public TestServer Server;
public Fixture()
{
_server = new TestServer(new WebHostBuilder()
.ConfigureAppConfiguration((context, conf) =>
{
conf.AddJsonFile(@Directory.GetCurrentDirectory() + "../appsettings.json");
}).UseStartup<Startup>()
.ConfigureServices(services =>
{
services.AddDbContext<CarDbContext>(options => options.UseInMemoryDatabase(Guid.NewGuid().ToString()));
})
);

Client = _server.CreateClient();
Server = _server;
}

//内部测试方法

using (var scope = _server.Host.Services.CreateScope())
{
var db = scope.ServiceProvider.GetRequiredService<CarDbContext>();
db.Database.EnsureDeleted();
Utilities.Seed(db);
}

和种子数据

public static class Utilities
{
public static void Seed(CarDbContext db)
{
db.Cars.Add(new Car("1", "White", "Toyota"));
db.SaveChanges(true);
}
}

我到底哪里做错了什么?在

中检索数据时我仍然得到 null
public async Task<Car> GetAsync(int id)
{
return await _carDbContext.Cars.FindAsync(id); //this always returns null
}

最佳答案

您不需要模拟上下文或您的服务。删除 _server = new TestServer 行之前的所有内容。在您的虚拟主机设置中,您已经将上下文设置为使用内存中提供程序,所以这就是所有必要的。上下文将被注入(inject)到服务中,服务将被注入(inject)到需要的地方。这里唯一改变的是上下文连接。它不会像 SQL Server 实例那样访问真实的东西,而是简单地从内存中存储和检索。

您唯一需要为测试做的另一件事是将要测试的数据植入“数据库”。在您的测试中,您需要访问测试服务器实例并执行以下操作:

using (var scope = _server.Host.Services.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<CarDbContext>();
context.EnsureDeleted();
// seed test data
}

// test code

关于c# - 在服务中注入(inject)模拟的 dbContext - 集成测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58326010/

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