首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

在.Net核心中运行Xunit测试时,为什么模拟DbContext在以与常规DbContext相同的方式初始化时为空

在.NET Core中运行Xunit测试时,模拟DbContext为空的问题通常是因为DbContext的初始化方式不正确或者模拟对象没有正确设置。DbContext是Entity Framework Core中的一个核心类,它代表与数据库的会话,可以用来查询和保存实体实例。在单元测试中,我们通常不希望实际连接到数据库,而是使用模拟(Mocking)来代替。

基础概念

  • DbContext: 是Entity Framework Core中的一个类,它提供了创建、读取、更新和删除数据库中数据的方法。
  • Xunit: 是一个流行的.NET测试框架,用于编写单元测试。
  • 模拟(Mocking): 在单元测试中,模拟是一种技术,用于创建和使用模拟对象来代替真实的对象,以便在不依赖外部系统的情况下测试代码。

相关优势

  • 隔离性: 使用模拟对象可以隔离测试代码,避免测试之间相互影响。
  • 速度: 模拟对象通常比真实对象执行得更快,因为它们不需要执行真实的数据库操作。
  • 可重复性: 模拟对象可以保证测试的可重复性,因为它们不会受到外部状态变化的影响。

类型

  • Mock对象: 使用专门的库(如Moq)创建的模拟对象。
  • Stub对象: 简单的对象,用于替代真实对象的部分功能。

应用场景

  • 当你需要测试不涉及数据库逻辑的业务逻辑时。
  • 当你需要避免测试中的数据库依赖时。

问题原因

模拟DbContext为空可能是因为:

  1. 初始化不正确: 在测试中,DbContext可能没有被正确初始化。
  2. 模拟对象设置不正确: 如果使用Moq等库模拟DbContext,可能没有正确设置模拟对象的行为。

解决方法

以下是一个使用Moq模拟DbContext的示例:

代码语言:txt
复制
using Moq;
using Xunit;
using Microsoft.EntityFrameworkCore;

public class MyServiceTests
{
    [Fact]
    public void TestMethod_ShouldNotBeNull()
    {
        // Arrange
        var mockSet = new Mock<DbSet<MyEntity>>();
        mockSet.As<IQueryable<MyEntity>>().Setup(m => m.Provider).Returns(new TestDbAsyncQueryProvider(mockSet.Object));
        mockSet.As<IQueryable<MyEntity>>().Setup(m => m.Expression).Returns(new MockExpression());
        mockSet.As<IQueryable<MyEntity>>().Setup(m => m.ElementType).Returns(typeof(MyEntity).GetTypeInfo().Assembly.GetTypes()[0]);
        mockSet.As<IQueryable<MyEntity>>().Setup(m => m.GetEnumerator()).Returns(new TestDbAsyncEnumerator(mockSet.Object));

        var mockContext = new Mock<MyDbContext>();
        mockContext.Setup(c => c.MyEntities).Returns(mockSet.Object);

        var service = new MyService(mockContext.Object);

        // Act
        var result = service.GetEntitiesAsync().Result;

        // Assert
        Assert.NotNull(result);
    }
}

public class MyDbContext : DbContext
{
    public DbSet<MyEntity> MyEntities { get; set; }
}

public class MyEntity
{
    public int Id { get; set; }
}

public class MyService
{
    private readonly MyDbContext _context;

    public MyService(MyDbContext context)
    {
        _context = context;
    }

    public async Task<IEnumerable<MyEntity>> GetEntitiesAsync()
    {
        return await _context.MyEntities.ToListAsync();
    }
}

public class TestDbAsyncQueryProvider<TEntity> : IDbAsyncQueryProvider
{
    private readonly IQueryProvider _inner;

    public TestDbAsyncQueryProvider(IQueryable<TEntity> queryable)
    {
        _inner = (IQueryProvider)queryable.Provider;
    }

    // Implement other required methods...
}

public class TestDbAsyncEnumerator<TEntity> : IDbAsyncEnumerator<TEntity>
{
    private readonly IEnumerator<TEntity> _inner;

    public TestDbAsyncEnumerator(IQueryable<TEntity> queryable)
    {
        _inner = queryable.GetEnumerator();
    }

    // Implement other required methods...
}

参考链接

确保在测试中正确设置模拟对象的行为,并且DbContext被正确初始化。这样,你就可以避免模拟DbContext为空的问题。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

【ASP.NET Core 基础知识】--测试--单元测试和集成测试

运行单元测试 在 ASP.NET Core 项目中,运行单元测试通常是通过测试运行器或者 .NET Core CLI 来实现的。...1.3 使用Moq进行模拟和依赖注入 模拟对象 在进行单元测试时,使用 Moq 进行对象模拟是一种常见的做法,特别是在测试依赖注入的情况下。Moq 可以帮助你模拟接口或虚方法,以便更容易地进行测试。...它们通常会返回预先定义好的值或者固定的行为,而不是模拟真实对象的行为。 Fake 对象:Fake 对象是一个实现了与真实对象相同的接口,但实现方式更加简化的对象。...TestServer 提供了一种方便的方式来模拟应用程序的运行环境,并进行集成测试,而无需启动一个真实的 Web 服务器。...通过这个示例,你可以编写一个集成测试来测试你的 ASP.NET Core 应用程序的行为,包括控制器、路由和中间件等。确保在测试结束后及时清理测试数据,以确保下次测试可以在干净的环境中运行。

38300

ABP入门系列(11)——编写单元测试

Effort.EF6:对基于EF的应用程序提供了一种便利的方式来进行单元测试。 XUnit:.Net上好用的测试框架。 Shouldly:断言框架,方便我们书写断言。 2.2....2.3. xUnit(.Net测试框架) xUnit专门为.Net Framework打造的一个免费的开源的单元测试工具。 同样,想对Xunit有更对了解,请直接访问xUnit 官方链接。...Shouldly(断言框架) Shouldly提供的断言方式与传统的Assert相比更实用易懂。...在构造函数中主要做了两件事,预置了初始数据和种子数据,并以默认租户Admin登录。 至此我们对abp为我们默认创建的测试项目有了一个大概的认识。下面我们就开始实战阶段。 3. 单元测试实战 3.1....理清要测试的方法逻辑 我们以应用服务层的TaskAppService的CreateTask方法为例,创建单元测试。

1.7K80
  • Entity Framework Core 2.0 新特性

    包含定义导航的实体是所有者。当查询所有者时,默认情况下将包含所有类型。 按照惯例,将为所属类型创建一个影子主键,并通过使用表分割将其映射到与所有者相同的表。...2.性能提升方面 2.1DbContext连接池 在ASP.NET Core程序中我们使用EF Core一般都是将自定义DbContext类型注册到依赖注入系统中,然后通过控制器中的构造函数参数获取该类型的实例...这意味着为每个请求创建一个新的DbContext实例。 所以在版本2.0中,我们引入了一种在依赖注入中注册自定义DbContext类型的新方式,它透明地引入了一个可重用的DbContext实例池。...一旦请求处理完成,实例上的任何状态都将重置,并且实例本身返回到池中。 这在思想概念上类似于ADO.NET中连接池的运作方式,并且能节省DbContext实例初始化成本。...这种新的支持允许以“安全”的方式使用C#字符串插值。这样就可以防止在运行时动态构建SQL时发生的常见SQL注入攻击.

    3.9K90

    从EFCore上下文的使用到深入剖析DI的生命周期最后实现自动属性注入

    使用EF的话不可避免要和DbContext打交道,在Core中的常规用法一般是:创建一个XXXContext类继承自DbContext,实现一个拥有DbContextOptions参数的构造器,在启动类...但是,通过构造函数这种方式来获取上下文实例其实很不方便,比如在Attribute或者静态类中,又或者是系统启动时初始化一些数据,更多的是如下一种场景: public class BaseController...在Asp.Net Core中,内置的DI有3种服务模式,分别是Singleton、Transient、Scoped,Singleton服务实例是保存在root provider中的,所以它才能做到全局单例...默认情况下,Asp.Net Core框架在创建HostBuilder的时候会判定当前是否开发环境,在开发环境下会开启这个验证: ? 所以前面那种关闭验证的方式是错误的。...Core在设计的时候为每个请求创建独立的Scope,这个Scope的provider被封装在HttpContext.RequestServices中。

    1.3K20

    Blazor一个简单的示例让我们来起飞

    Blazor Blazor他是一个开源的Web框架,不,这不是重点,重点是它可以使c#开发在浏览器上运行Web应用程序.它其实也简化了SPA的开发过程....Blazor可以让.NET附有全栈开发功能,它可以使Web开发变得轻松而高效.而且Blazor是开源的,它得到了社区的大力支持,而且发展速度会很快....@page他定义了该页面的url,当然在razor中也是这样的,而且下最下面我通过HttpClient进行我们的api调用,在这 System.Net.Http.Json这篇文章中我们也可以看到他简直就是为了我们...而且在我的代码中最后一部分有一个@functions片段,它包含了页面所有的业务逻辑,在我们页面初始化时我们通过OnInitializedAsync方法进行调用我们的api然后将其进行填充赋值并填充到我们的...,并且我们必须一直与服务端保持连接才行.如果说切换到WebAssembly客户端版本,限制是完全不同的,但是目前来说的话他首次需要下载一些运行时文件到浏览器中.

    1.3K10

    Entity Framework Core 2.0 入门

    // 创建测试项目 为解决方案添加项目: dotnet sln add LearnEf.UI/LearnEf.UI.csproj dotnet sln add LearnEf.Domains/LearnEf.Domains.csproj...这里, 常规的做法是, 针对开发时的数据库, 可以通过命令直接创建和更新数据库. 而针对生产环境, 最好是生成sql脚本, 然后由相关人员去执行这个脚本来完成数据库的创建或者更新....在解决方案里再建立一个asp.net core mvc项目: mkdir LearnEf.Web && cd LearnEf.Web dotnet new mvc 在解决方案里添加该项目: dotnet.../LearnEf.Data/LearnEf.Data.csproj 为测试项目添加该项目引用: cd ../*Tests dotnet add reference .....非常简单, 从log可以看到, 删除动作只用到了主键: 如果是删除的离线model, 那么Remove方法首先会让Dbcontext追踪这个model, 然后设置状态为Deleted.

    3.2K80

    Entity Framework Core 2.0 入门

    // 创建测试项目 为解决方案添加项目: dotnet sln add LearnEf.UI/LearnEf.UI.csproj dotnet sln add LearnEf.Domains/LearnEf.Domains.csproj...这里, 常规的做法是, 针对开发时的数据库, 可以通过命令直接创建和更新数据库. 而针对生产环境, 最好是生成sql脚本, 然后由相关人员去执行这个脚本来完成数据库的创建或者更新....在解决方案里再建立一个asp.net core mvc项目: mkdir LearnEf.Web && cd LearnEf.Web dotnet new mvc 在解决方案里添加该项目: dotnet.../LearnEf.Data/LearnEf.Data.csproj 为测试项目添加该项目引用: cd ../*Tests dotnet add reference .....非常简单, 从log可以看到, 删除动作只用到了主键: 如果是删除的离线model, 那么Remove方法首先会让Dbcontext追踪这个model, 然后设置状态为Deleted.

    3.5K140

    【译】MongoDB EF Core 提供程序:有什么新功能?

    接下来,让我们在刚刚添加的两行代码中添加一个断点,以确保我们可以在继续操作时实时跟踪更改。选择“开始调试”按钮来运行应用程序。当第一个断点被击中时,我们可以看到本地字段值已被分配。...Jaws: The Revenge Shark Night D 如果您想查看发送到服务器的查询(在本例中为 MQL),那么您可以在 DbContext 上的 Create 函数中启用日志记录,如下所示...这意味着默认情况下,SaveChanges 和 SaveChangesAsync 是事务性的。这将使生产级工作负载中的操作在发生任何故障时自动回滚,并确保所有操作都以乐观并发的方式完成。...如果您想关闭事务,您可以在调用任何 SaveChanges 操作之前的初始化阶段进行关闭。...我们还将添加第三部分(是的,这是三部曲),但使用与第二部电影实体相同的 ID 到这个新上下文,然后保存我们的更改。

    7110

    面向初学者的 Entity Framework Core

    它允许开发人员使用.NET对象来操作数据库,从而无需编写大多数SQL查询语句。EF Core通过对数据库交互的复杂性进行抽象,使得数据访问代码更易于维护、扩展和测试。...在深入了解EF Core之前,理解什么是ORM非常重要。ORM(对象关系映射)是软件开发中用于在不兼容的系统(如数据库和编程语言)之间转换数据的一种技术。...简单来说,ORM允许你使用面向对象编程的方式与数据库进行交互,而无需编写原始的SQL查询语句。 为什么使用实体框架核心?...EF Core中的关键概念 DbContext: DbContext是EF Core中的核心类,用于管理数据库交互操作。它充当了.NET应用程序与数据库之间的桥梁。...;Database=SchoolDB;Trusted_Connection=True;"); } } 步骤4:创建并应用迁移 要创建初始数据库,按照前面介绍的方法生成迁移: dotnet ef

    10310

    【半译】在ASP.NET Core中创建内部使用作用域服务的Quartz.NET宿主服务

    在我的上一篇文章中,我展示了如何使用ASP.NET Core创建Quartz.NET托管服务并使用它来按计划运行后台任务。...不幸的是,由于Quartz.NET API的工作方式,在Quartz作业中使用Scoped依赖项注入服务有些麻烦。说明下这篇文章部分采用机翻。...,但是在执行的我们请求的IJob之前,我们从DI容器中解析了DbContext和消息总线服务。...但是,此处显示的方法并不是在工作中使用范围服务的唯一方法。马修·阿伯特(Matthew Abbot) 在这个文章中演示了一种方法,该方法旨在以正确处理运行后的作业的方式实现IJobFactory。...总结 在本文中,我展示了如何创建中间层IJob,该中间层QuartzJobRunner在调度程序需要执行作业时创建。

    1.9K10

    【初学者指南】在ASP.NET MVC 5中创建GridView

    从对话框中跳转到 Web,选择 ASP.NET Web 应用程序项目,然后单击确定。 ? 在模板中选择 MVC,如果编写了应用的单元测试,请先做检查,并点击 OK。 我们的工程都是用基本的功能创建的。...现在,在控制器文件夹中添加一个空的名为 AssetController 的控制器,这个控制器件将用于所有 Asset 的相关工作。...在我们的案例里,我们将会以每一个需求的方式将其安装在 GridExampleMVC web 中,然后点击安装按钮。 ?...在写控制器代码之前,我们需要为实体框架配置连接字符串,以便在操作数据库时来连接数据库。因此,我们的连接字符串应该被指定给一个有效的数据源,以便我们在运行时应用不会被打断。...HTML 实现渲染的代码,请为检索行为创建一个空模板(没有模型)的视图,然后在其中添加如下代码: @model IEnumerable <div

    6.2K90

    迁移 appseting.json 创建自定义配置中心

    自使用.NET Core框架以来,配置大多存在json文件中: 【框架默认加载配置】文件为appseting.json 以及ppsettings.Environment.json, 【环境变量】存在...所以笔者创建一个自定义的以EFCore作为配置源的配置中心去解决以上两个问题,并且把他封装成一个类库,可适用于多场景。...数据库切换 想要解决数据库切换的问题,首先就是把配置构建从Program类中抽离出来,重新构建一个类去创建配置所用到的IConfiguration,故我将配置的初始写在静态方法中,通过传递连接字符串以及数据库类型的方式去构建不同的上下文...还记得我们最开始说的:不修改原始的IConfiguration读取方式的情况下创建自定义配置中心,故他的使用方式与原始的IConfiguration相差不大,只是加入了初始化步骤。...我们测试使用一段复杂的json结构看能取到怎样的节点数据。

    1.2K40

    .NET 5.NET Core使用EF Core 5连接MySQL数据库写入读取数据示例教程

    本文首发于《.NET 5/.NET Core使用EF Core 5(Entity Framework Core)连接MySQL数据库写入/读取数据示例教程》 前言 在.NET Core/.NET 5的应用程序开发...而将.NET Core/.NET 5应用程序与SQL Server数据库的ORM组件有微软官方提供的EF Core(Entity Framework Core),也有像SqlSugar这样的第三方ORM...本文将为大家分享的是在.NET Core/.NET 5应用程序中使用EF Core 5连接MySQL数据库的方法和示例。...创建示例项目 使用Visual Studio 2019(当然,如果你喜欢使用VS Code也是没有问题的,笔者还是更喜欢在Visual Studio编辑器中编写.NET代码)创建一个基于.NET 5的Web...); } } } } 访问地址:http://localhost:8166/api/people/create 来向MySQL数据库写入测试数据,返回结果为

    8K42

    Entity Framework 4.1 Code-First 学习笔记

    (上下文需要派生自DbContext)中时,会自动生成相应的数据表。...我们将增加一个静态的构造函数,这个静态的构造函数对于整个应用程序域来说建立一个标准,当数据库的上下文初始化的时候,检查数据库的架构是否与模型相符,如果不是的话,将删除数据库然后重新创建它。...默认情况下,将在你的本地机器上,使用上下文对象名称,有许多方式来覆盖这个行为,最简单的方式是在配置文件中增加一个名字为上下文对象名称的数据库连接串,在我这里,叫做 MyDomainContext,还可以通过实现一个构造函数...这就是为什么需要标记你的子实体集合属性为 virtual 的原因。...延迟加载:非常宽容,因为只在需要的时候加载数据,不需要预先计划;可能因为数据访问的延迟而降低性能,考虑到每访问父实体的子实体时,就需要访问数据库。两种方式各有优缺点,该怎么选择呢?

    1.6K10

    Entity Framework应用:使用Code First模式管理数据库创建和填充种子数据

    一、管理数据库连接 1、使用配置文件管理连接之约定 在数据库上下文类中,如果我们只继承了无参数的DbContext,并且在配置文件中创建了和数据库上下文类同名的连接字符串,那么EF会使用该连接字符串自动计算出数据库的位置和数据库名...出现上面报错的原因是因为数据库上下文发生了改变,与现有数据库不匹配。解决方案: 1、把数据库里面的迁移记录表删掉或者重命名即可。 重新运行程序,结果如下: ?...这在开发周期的早期阶段通常很有用(比如设计领域实体时),从单元测试的角度也很有用。...") { Database.SetInitializer(null); } 2、填充种子数据 到目前为止,无论我们选择哪种策略初始化数据库,生成的数据库都是一个空的数据库...此外,开发阶段可能想以admin的资格为其填充一些数据,或者为了测试应用在特定的场景中表现如何,想要伪造一些数据。

    1.2K20

    .NET 云原生架构师训练营(模块二 基础巩固 EF Core 介绍)--学习笔记

    仓储 在领域层和数据映射层之间,像一个内存级别的领域对象集合 为领域业务的单元测试提供替换点 集中数据库访问逻辑 ?...UnitOfWork 工作单元 一个工作单元在一个事务范围内保留所有对数据库的变更,在这个工作单元结束的时候一次性提交所有改动到数据库 DB Context 与 DB Set DB Context(UnitOfWork...工作单元) DB Set(Repository 仓储) EF Core 提供一个 DB Context 和多个 DB Set 组合完成数据查询和更新操作的 ORM 框架 EF Core快速开始示例 创建一个空的...DbContext 完成数据查询与插入 创建实体 Entity namespace LighterApi.Data { public class Entity { //...完成数据查询与插入 初始化数据库 ,注意在初始化以前确保正确配置了连接字符串,并且在startup.cs中添加了DbContext的注入 // 安装dotnet tool ef工具 dotnet tool

    82310

    ASP.NET Core 依赖注入(DI)简介

    以这种方式,可以将复杂的依赖关系图提供给类,而不需要任何硬编码的对象构造。 除了创建具有依赖关系的对象之外,容器通常会在应用程序中管理对象生命周期。...与CharacterRepository类一起使用DI的方式是您可以遵循所有应用程序服务的一般模型,而不仅仅是在“仓库”或数据访问类中。...依赖注入以这种链式方式使用是不寻常的,每个请求的依赖依次请求自己的依赖关系。 容器负责解析图中的所有依赖关系,并返回完全解析的服务。...注意: 在一个单例中从容器中实例化一个声明周期为Scoped的服务,在这种情况下,在处理后续请求时,服务可能会处于不正确的状态。 具有依赖关系的服务应在容器中注册。...Singleton Singleton生命周期服务是在第一次请求时创建的(或者当你在指定实例时运行ConfigureServices时),然后每个后续请求都将使用相同的实例。

    3K40

    ASP.Net Core 开发笔记

    关于 dotNet core 中的依赖注入和 IoC 可以参考 - ASP.NET Core中的依赖注入(1):控制反转(IoC) 运行时 ASP.NET Core 应用启动时读取ASPNETCORE_ENVIRONMENT...DbContext里的OnModelCreating(). 使用Unit of Work + Repository模式 Repository模式 为什么要使用Repository模式?...与持久化技术无关. 易于测试. 代码重用. 依赖注入, 松耦合, DIP原则. DIP, 也就是SOLID里面的D, 高级别的模块不应该依赖于低级别的模块, 它们都应该依赖于抽象 ?...为什么要使用Unit of Work模式? DbContext已经实现了Unit of Work 和 Repository 模式. Controller等不应该直接使用DbContext....Uow 和 Repository模式 的关系即: 工作单元服务于仓储,并在工作单元中初始化上下文,为仓储单元提供上下文对象,由此确保同一上下文对象。

    1.8K10
    领券