【问题标题】:Auto increment primary key in mocked db context模拟数据库上下文中的自动递增主键
【发布时间】:2021-02-13 20:36:51
【问题描述】:

有谁知道我如何在我的模拟数据库上下文中拥有自动递增主键?我正在对一种方法进行单元测试,当我想将两个项目添加到我的模拟数据库上下文时,我收到一条错误消息,提示“已添加具有相同键的项目”。所以我应该找到一种方法来设置我的数据库上下文模拟,这样每次添加项目时,都会添加不同的主键。 这是我在服务类中的方法:

public async Task<ProductDTO> CreateProduct(ProductDTO dto)
{
 foreach (var i in dto.Products)
            {
                if (i.ProductId == 0)
                {
                    // New product
                    var product = Product.CreateMyProductDto(i);
                    _db.Products.Add(product);
                }
            }

 // rest of the code …

}

所以在这里我们查看 dto.products,如果任何产品的 productId 为零,那么我们通过调用 Product.CreateMyProductDto 函数来创建我们的产品并将其添加到 Products 表中。在下面的单元测试中,我有两个 productId = 0 的产品,因此它们应该添加到 Products 表中,但由于主键,我在添加第二个产品时出错。

[Fact]
public async Task TestForCreateProduct()
{
    //Arrange
     List<Product> products = new List<Product>();

     Product product1 = new Poduct()
     {
           ProductId = 0
     };

     Product product2 = new Poduct()
     {
          ProductId = 0
     };

     // add to the products list
      products.Add(product1);
      products.Add(product2);
      
      ProductDTo dto = new ProductDTO()
      {     
          Products = products
      };

     // create mock
     DbContextMock<MyContext> context_Moq = new DbContextMock<MyContext>(DummyOptions);
        
     // set up mock
     context_Moq.CreateDbSetMock(x => x.Products, new[]
     {
          new Product { EntityId = 1, Name = "product1"},
          new Product { EntityId = 2, Name = "product2"},
          new Product { EntityId = 3, Name = "product3"}
     });

     var service = new myService(context_Moq.Object);

     // Act
     var result = await service.CreateProduct(dto);
          
     // Assert
     Assert.Equal(5, context_Moq.Object.Products.Count());
}

我正在使用 .NET core3,所以任何人都可以帮我解决这个错误吗?我需要在我的模拟数据库上下文中拥有自动递增的主键。

【问题讨论】:

  • 不要模拟DbContext,而是使用内存中选项和内存中提供程序或启用内存选项的Sqlite提供程序。

标签: c# unit-testing .net-core moq xunit


【解决方案1】:

我终于可以解决这个问题了。如下所示,EntityId 是我的 Product 类中的主键,我使用 [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] 属性来为 EntityId 设置自动增量标识列

public class Product
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public long EntityId { get; set; }
       
      // rest of the code
}

在这种情况下,项目被添加到我的模拟 dbContext 中,EntityIds 从 1 开始。 假设您使用具有 EntityId 1 的一项设置您的 dbContext。然后 您调用 Add 函数将产品添加到 Products 表中,您将收到相同的错误,因为它尝试添加已在您的模拟 dbContext 中的 EntityId 1 的产品。所以具有相同键的项目不能在数据库中。 在 2 种情况下,您不得将此属性用作主键:

  1. 如果您的主键是外键
  2. 当您的主键上有 ValueGeneratedNever() 方法时

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-25
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    • 2015-06-08
    • 2011-02-05
    • 2012-03-13
    • 2011-09-02
    相关资源
    最近更新 更多