只向内存数据库中添加一次记录



我正试图用数据库编写我的第一个xunit测试,而不是像在文章中读到的那样嘲笑DbContext,我使用了inMemoryDatabase,所以我喜欢遵循

公共类GetCustomersTest{DbContextOptions _context;

public GetCustomersTest()
{
if (_context==null)
_context = CreateContextForCustomer();
}        

[Theory]
[InlineData(1)]
[InlineData(2)]
public void GetCustomerById_ShouldReturnCorrectObject(int id)
{
using (var context = new DataBaseContext(_context))
{
var customerByIdService = new GetCustomerByIdService(context);

var customer = customerByIdService.Execute(id);
var customerActual = context.Customers.Where(x => x.Id == id).SingleOrDefault();
var customerTmp = new Customer()
{
Id = id,
FirstName = customer.Data.FirstName,
LastName = customer.Data.LastName,
Phone = customer.Data.Phone,
ClientNote = customer.Data.ClientNote
};
Assert.Equal(customerTmp.FirstName, customerActual.FirstName);
Assert.Equal(customerTmp.LastName, customerActual.LastName);
Assert.Equal(customerTmp.Phone, customerActual.Phone);
Assert.Equal(customerTmp.ClientNote, customerActual.ClientNote);
}
}
private DbContextOptions<DataBaseContext> CreateContextForCustomer() {
var options = new DbContextOptionsBuilder<DataBaseContext>()
.UseInMemoryDatabase(databaseName: "SalonDatabase")
.Options;
using (var context = new DataBaseContext(options))
{
context.Customers.Add(new Customer
{
Id = 1,
FirstName = "User1",
LastName = "Surname1",
Phone = "123",
ClientNote = ""
});
context.Customers.Add(new Customer
{
Id = 2,
FirstName = "User2",
LastName = "Surname2",
Phone = "4567",
ClientNote = "The best"
});

context.SaveChanges();
}
return options;
}
}

它在[InlineData(1(]上可以查找,但当涉及到[InlineData(2(]时,它似乎又开始运行构造函数,所以当它想将customerdata添加到表中时,它说具有该Id键的记录存在。这样做的最佳方法是什么?

在构建数据库上下文选项时,为数据库名称添加一个GUID以使其唯一:

var options = new DbContextOptionsBuilder<DataBaseContext>()
.UseInMemoryDatabase(databaseName: "SalonDatabase" + Guid.NewGuid().ToString())
.Options;

或者,如果你使用的是一个足够新的语言版本,你可以使用字符串插值而不是级联:

var options = new DbContextOptionsBuilder<DataBaseContext>()
.UseInMemoryDatabase(databaseName: $"SalonDatabase{Guid.NewGuid()}")
.Options;

如果这样做,那么每个测试都会使用一个全新的数据库,不受以前任何测试的影响。

正如@MicheleMassari所说,遵循Arrange-Act Assert模式是一种很好的做法,这样就可以清楚地知道哪些行正在为测试做准备,哪些行正在执行你想要测试结果的操作。

  1. 排列输入和目标。安排步骤应该设置测试用例。测试是否需要任何物体或特殊设置?它需要准备一个数据库吗?它需要登录到网络应用程序吗?在测试开始时处理所有这些操作
  2. 对目标行为采取行动。行动步骤应该涵盖要测试的主要内容。这可以是调用函数或方法,调用RESTneneneba API,或者与网页交互。将行动集中在目标行为上
  3. 断言预期结果。行动步骤应该引起某种反应。断言步骤验证该响应的好坏。有时,断言就像检查数值或字符串值一样简单。其他时候,它们可能需要检查系统的多个方面。断言将最终决定测试是通过还是失败

该页面中的代码示例是用Python而不是C#编写的,但该模式对任何语言的单元测试都有效。在测试的情况下,以这种方式构建测试可以清楚地表明您是在测试GetCustomerByIdService.Execute还是实体框架的Where方法的行为。

最新更新