【问题标题】:.net core mocking dbcontext not working (static issue?).NET核心模拟DBContext不起作用(静态问题?)
【发布时间】:2019-07-02 02:42:01
【问题描述】:

我正在尝试测试 .net core 2.2 api。我很难模拟(使用起订量)dbcontext。使我的 mockDbContext 可用的语法是什么。我收到 NullReferenceException。由于我相信 Changetracker 从未实例化过。我需要不同的方法吗?我看到提到了 .UseInMemoryDatabase(),但是文档或很好的例子很少。

以下是我尝试在测试中使用的代码 [事实]。

     var mockDbContext = new Mock<dbContext>(optionsBuilder.Options);
     var controller = new HomeController(mockDbContext.object);

然后使用控制器测试...为简洁起见删除

var datafromdbcontext = controller.GetData();

以下是我的 dbcontext 示例。

    public class dbContext:DbContext
    {
        public dbContext(DbContextOptions<dbContext> options)
        : base(options)
        {
            //MAKE IT READONLY
            ChangeTracker.QueryTrackingBehavior = 
       QueryTrackingBehavior.NoTracking;
        }

【问题讨论】:

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


    【解决方案1】:

    有很多使用 InMemory 数据库的示例(这是您通常用于单元测试的)...这是一个示例:https://docs.microsoft.com/en-us/ef/core/miscellaneous/testing/in-memory

    您不应该尝试模拟实际上下文,而是使用 InMemory 选项。所以 - 你的上下文,但使用 InMemory “选项”......就像这样:

    var myFakeContext = new DbContextOptionsBuilder<MYDBCONTEXT>().UseInMemoryDatabase("SO-MADE-UP-NAME"); 
    

    【讨论】:

    • 如果我有起订量问题,我应该使用 .InMemoryDatabase()?
    • 是的,事实上在 EF Core 中你根本不应该模拟你的 DbContext,而是选择 InMemoryDatabase
    • @Sangman 打败了我。是的,所以,你不应该尝试模拟实际的上下文,而是使用 InMemory 选项。所以-您的上下文,但使用 InMemory “选项”...我已将示例添加到答案中
    • 是的,使用 InMemoryDatabase 看看它能让你走多远。内存中有些东西不支持。如果您需要模拟 FromSql(例如,调用存储过程),请在此处查看我的示例:github.com/efarr/mock-ef-core-fromsql
    • @Fabio - 这完全取决于您要测试的内容以及您要实现的目标。出于不同的原因设计了两种不同类型的测试。您所指的一种称为集成测试,它与单元测试根本不同。模拟通常(但不一定总是)在“单元测试”中发挥作用。
    【解决方案2】:

    我创建了一个库,可在 NuGet 和 GitHub 上使用,名为 EntityFrameworkCoreMock,它负责完成所有设置的繁重工作。还有一个 Moq 的实现。

    https://github.com/huysentruitw/entity-framework-core-mock

    使用示例

    public class User
    {
        [Key, Column(Order = 0)]
        public Guid Id { get; set; }
    
        public string FullName { get; set; }
    }
    
    public class TestDbContext : DbContext
    {
        public TestDbContext(DbContextOptions<TestDbContext> options)
            : base(options)
        {
        }
    
        public virtual DbSet<User> Users { get; set; }
    }
    
    public class MyTests
    {
        [Fact]
        public void Test()
        {
            var initialEntities = new[]
            {
                new User { Id = Guid.NewGuid(), FullName = "Eric Cartoon" },
                new User { Id = Guid.NewGuid(), FullName = "Billy Jewel" },
            };
    
            var dbContextMock = new DbContextMock<TestDbContext>(DummyOptions);
            var usersDbSetMock = dbContextMock.CreateDbSetMock(x => x.Users, initialEntities);
    
            // Pass dbContextMock.Object to the class/method you want to test
    
            // Query dbContextMock.Object.Users to see if certain users were added or removed
            // or use Mock Verify functionality to verify if certain methods were called: usersDbSetMock.Verify(x => x.Add(...), Times.Once);
       }
    
        public DbContextOptions<TestDbContext> DummyOptions { get; } = new DbContextOptionsBuilder<TestDbContext>().Options;
    }
    

    【讨论】:

      猜你喜欢
      • 2019-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-09
      • 2017-06-03
      • 2018-04-04
      相关资源
      最近更新 更多