将记录添加到内存数据库一次

adding records to inmemorydatabase just once

我正在尝试使用数据库编写我的第一个 xunit 测试,而不是模拟 DbContext 我在文章中阅读时使用了 inMemoryDatabase,所以我喜欢以下内容

public class 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)] 时,它似乎又开始 运行 构造函数,所以它想添加客户数据到 table,它表示使用该 Id 键 exists.what 的记录是最好的方法?

构建数据库上下文选项时,将 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. Arrange inputs and targets. Arrange steps should set up the test case. Does the test require any objects or special settings? Does it need to prep a database? Does it need to log into a web app? Handle all of these operations at the start of the test.
  2. Act on the target behavior. Act steps should cover the main thing to be tested. This could be calling a function or method, calling a REST API, or interacting with a web page. Keep actions focused on the target behavior.
  3. Assert expected outcomes. Act steps should elicit some sort of response. Assert steps verify the goodness or badness of that response. Sometimes, assertions are as simple as checking numeric or string values. Other times, they may require checking multiple facets of a system. Assertions will ultimately determine if the test passes or fails.

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