首页 > 解决方案 > 在 C# Net Core 3.1 单元测试中自动生成标识列

问题描述

我的基础课

    public class Book {
        public int Id { get; set;}
        public string Title { get; set;} 
    }
    public class Author {
        public Author () {
            BookList = new HashSet<Book> ();
            for (int i = 0; i< 10; i++) {
                var book = new Book() {
                    Title = "Funny book" + i;
                }
                BookList.Add(book);
            }
        }
        public int Id { get; set;}
        public string Name { get; set;}
        public ICollection<Book> BookList { get; set; }
    }

我的存储库类

        public interface IBookRepository
    {       
        Task<Book> CreateBook(Book book);
    }
    public class BookRepository : IBookRepository
    {
        public BookRepository(BookStoreContext context)
             : base(context)
        {
        }
        public async Task<Book> CreateBook(Book book)
        {
            if (book == null)
                throw new ArgumentNullException("book cannot be null");
            }
            Context.Book.Add(book);
            await Context.SaveChangesAsync().ConfigureAwait(false);

            return book;
        }           
    }

我正在使用以下实用程序类设置我的单元测试

    public static class AuthorData
    {
        public static List<Author> GetData()
        {
            List<Author> authors = new List<Author>();
            Author author1 = new Author()
            {
                Id = 100,
                Name="author1"
            };
            authors.Add(author1);
            Author author2 = new Author()
            {
                Id = 200,
                Name="author2"
            };
            authors.Add(author2);
        }
    }
    public static class BookData
    {
        public static List<Book> GetData()
        {
            List<Book> books = new List<Book>();
            Book book1 = new Book()
            {
                Id = 1000,
                Name="Wonderful book 1"
            };
            books.Add(book1);
            Book book2 = new Book()
            {
                Id = 1001,
                Name="Wonderful book 2"
            };
            books.Add(book2);
        }
    }
      public class AuthorContextMock
      {
         public static BookStoreContext ConfigureSensorContext(IServiceCollection services)
          {
            services.AddDbContext<BookStoreContext>(c =>
         c.UseInMemoryDatabase(Guid.NewGuid().ToString())
        .UseQueryTrackingBehavior(QueryTrackingBehavior.TrackAll)
        .EnableDetailedErrors()
        .EnableSensitiveDataLogging());
         var serviceProvider = services
        .AddEntityFrameworkInMemoryDatabase()
        .BuildServiceProvider();
         var Context = serviceProvider.GetRequiredService<BookStoreContext>();
         Context.Database.EnsureCreated();

         Context.Authors.AddRange(AuthorData.GetData());
         Context.Books.AddRange(BookData.GetData());
         Context.SaveChanges();
         return Context;
        }
    }

我的单元测试

[Fact]
    public async Task CreateBookTest()
    {       
        var context = BookContextMock.ConfigureBookContext(new ServiceCollection());
        BookRepository repo = new BookRepository(context);
        Book book = new BookSensor()
        {
            Title = "New Book 1",
        };
        var newBook = await repo.CreateBook(book);
    }

在单元测试方法中,如果我没有为 book 对象指定 Id,它会抛出一个错误,指出 Id = 1000 的对象已被另一个实体跟踪。

这是我的推理:

(1) 当我创建作者测试数据时,它为每个作者创建了一些书籍。由于字段是 SQL 表的 Identity 列,因此在创建书籍时未指定 Id。

(2) 然后,我用指定的 ID 创建了我的图书测试数据。测试数据创建成功。

(3) 在单元测试期间,系统似乎对选择下一个可用 ID 感到困惑。

有没有办法在不指定 ID 的情况下解决问题?

单元测试适用于 netcore 2.1。单元测试转换为net core 3.1后,问题就出现了。

标签: c#.net-coreintegration-testingxunit.netin-memory-database

解决方案


如果您将 Book 类的定义更改为:

public class Book {
    public string Id { get; set;}
    public string Title { get; set;} 
}

您可以使用以下方法即时生成新的 guid 来添加其他书籍:

Guid g = Guid.NewGuid();

然后,当您创建新书时,只需调用 g.ToString() 即可获取基础值并将其分配给 Id 属性。当然,您还必须更改后端数据库表的结构以支持这一点。


推荐阅读