Dot Net 核心应用程序的 Xunit 单元测试

2024-02-13

我最近开始学习单元测试,现在需要使用 Xunit 和 Moq 为 dot net core 应用程序编写单元测试。

我可以编写一些非常基本的内容,但是当为复杂的类编写它们时,我有点陷入困境。

下面是我将要为其编写测试的课程。

 public class AgeCategoryRequestHandler : IInventoryRequestHandler<InventoryRequest, HandlerResult>
{
    private readonly IRepositoryResolver _repositoryResolver;
    Hotels.HBSI.Logging.ILogger logger;
    public AgeCategoryRequestHandler(IRepositoryResolver repositoryResolver, Hotels.HBSI.Logging.ILogger iLogger)
    {
        _repositoryResolver = repositoryResolver;
        logger = iLogger;
    }

    public async Task<HandlerResult> Run(InventoryRequest inventoryRequest)
    {
        var result = await ProcessRequest(inventoryRequest);
        return CreateResponse(inventoryRequest, result);
    }

    private async Task<int> ProcessRequest(InventoryRequest inventoryRequest)
    {
        logger.Info("AgeCategory requesthandler processrequest start");
        var repository = _repositoryResolver.ResolveEstabAgeCategory();
        if (repository is not null)
        {
            return await repository.InsertUpdateEstabAgeCategoryDetail(inventoryRequest.EstabAgeCategories)
           .ConfigureAwait(false);
        }
        logger.Info("AgeCategory requesthandler processrequest complete");
        return InernalError.reponotfound;
    }
    public HandlerResult CreateResponse(InventoryRequest inventoryRequest, int resultCount)
    {
        var requestCount = inventoryRequest.EstabAgeCategories.Count;
        var handlerResult = new HandlerResult() { Id = RequestHandlerEnum.AgeCategrory.ToInt() };
        if (requestCount > 0 && resultCount < requestCount)
        {
            handlerResult.IsSuccess = false;
            handlerResult.ErrorCode = OTAErrorType.InvalidAgeCategory.ToInt();
        }
        else if (requestCount > 0 || requestCount == resultCount)
        {
            handlerResult.IsSuccess = true;
            handlerResult.ErrorCode = 0;
        }
        return handlerResult;
    }
}

首先,IRepositoryResolver 和 ILogger 位于构造函数中,因此我为它们创建了模拟,但无法超越它,因为我仍处于学习的初始阶段。

有人可以向我解释一下实现这一目标的步骤/方法吗?

编辑:到目前为止我所做的如下(无法弄清楚要做什么以及从哪里开始或写)

编辑2:对我的测试代码进行了更多修改,如果我的方向正确,有人可以发表评论吗?我还能测试什么?

 public class AgeCategoryRequestHandlerTest
{
    private AgeCategoryRequestHandler _ageCategoryRequestHandler;

    private readonly Mock<AgeCategoryRequestHandler> _ageCategory = new Mock<AgeCategoryRequestHandler>();

    private readonly Mock<Hotels.HBSI.Logging.ILogger> _mockLogger = new Mock<Hotels.HBSI.Logging.ILogger>();
    private readonly Mock<IRepositoryResolver> _mockRepositoryResolver = new Mock<IRepositoryResolver>();
    public AgeCategoryRequestHandlerTest()
    {

        _ageCategoryRequestHandler = new AgeCategoryRequestHandler(_mockRepositoryResolver.Object, _mockLogger.Object);


    }


    [Fact]


   public async void  Testtt()

    {
        var fixture = new Fixture();
        var inventory = fixture.Create<InventoryRequest>();
        var hndlr = fixture.Create<HandlerResult>();

        hndlr.ErrorCode = 0;
        int resultCount = 3;

        await _ageCategoryRequestHandler.Run(inventory);

        HandlerResult response =   _ageCategoryRequestHandler.CreateResponse(inventory, resultCount);

        Assert.Equal(hndlr.ErrorCode, response.ErrorCode);

     
    }

尝试运行 Chris B 建议的代码,但出现类型转换错误EstabAgeCategories = new List<int>

现在我已经使用固定装置来创建自动对象并执行了一些断言值。下面是代码示例

           var fixture = new Fixture();
        var inventoryRequest = fixture.Create<InventoryRequest>();
        
        _mockRepository
            .Setup(x => x.InsertUpdateEstabAgeCategoryDetail(inventoryRequest.EstabAgeCategories))
            .ReturnsAsync(6);

        _mockRepositoryResolver
            .Setup(x => x.ResolveEstabAgeCategory())
            .Returns(_mockRepository.Object);

        // act
        var result = await _ageCategoryRequestHandler.Run(inventoryRequest);

        // assert
        _mockRepository
            .Verify(x => x.InsertUpdateEstabAgeCategoryDetail(inventoryRequest.EstabAgeCategories), Times.Once);

        Assert.True(result.Id == 6);
        Assert.True(result.ErrorCode == 0);
        Assert.True(result.IsSuccess);

从您发布的单元测试代码来看,您似乎对测试内容感到困惑。

查看您的类并确定您的“公共”接口,即可以从代码的其他部分调用哪些方法。您实际上应该只测试公共方法。私有方法通常通过公共方法进行测试。

看着AgeCategoryRequestHandler,你有两个公共方法 -Run and CreateResponse。我想问是否CreateResponse需要公开,但我们暂时保留它。对于这些方法中的每一个,您都希望断言返回值是给定输入值时所期望的值。

private AgeCategoryRequestHandler _ageCategoryRequestHandler;

// Not needed
private readonly Mock<AgeCategoryRequestHandler> _ageCategory = new Mock<AgeCategoryRequestHandler>();

private readonly Mock<Hotels.HBSI.Logging.ILogger> _mockLogger = new Mock<Hotels.HBSI.Logging.ILogger>();
private readonly Mock<IRepositoryResolver> _mockRepositoryResolver = new Mock<IRepositoryResolver>();

public AgeCategoryRequestHandlerTest()
{
    _ageCategoryRequestHandler = new AgeCategoryRequestHandler(_mockRepositoryResolver.Object, _mockLogger.Object);
}

单元测试的设置正在以正确的方式进行 - 您已经为依赖项创建了模拟,但我看到您已经为要测试的类创建了模拟 - 这是不需要的,可以删除。您想要测试您在构造函数中初始化的实际类本身。

public async Task<HandlerResult> Run(InventoryRequest inventoryRequest)
{
    var result = await ProcessRequest(inventoryRequest);
    return CreateResponse(inventoryRequest, result);
}

private async Task<int> ProcessRequest(InventoryRequest inventoryRequest)
{
   _logger.LogInformation("AgeCategory requesthandler processrequest start");

    var repository = _repositoryResolver.ResolveEstabAgeCategory();

    if (repository != null)
    {
        return await repository.InsertUpdateEstabAgeCategoryDetail(inventoryRequest.EstabAgeCategories).ConfigureAwait(false);
    }

    _logger.LogInformation("AgeCategory requesthandler processrequest complete");

    return 0;
}

我们可以测试公众Run通过查看该方法并了解执行时它将执行的操作来了解该方法。首先,它将调用一个私有方法ProcessRequest。里面ProcessRequest, the IRepositoryResolver将使用依赖关系。这意味着我们需要在单元测试中“设置”这种依赖关系以满足if (repository != null)健康)状况。

我假设IRepositoryResolver返回另一个接口(?) - 类似于:

public interface IRepository
{
    Task<int> InsertUpdateEstabAgeCategoryDetail(List<int> x);
}

因此,在单元测试中,您需要为从返回的存储库创建一个模拟IRepositoryResolver:

private readonly Mock<IRepository> _mockRepository = new Mock<IRepository>();

然后,您需要设置模拟IRepositoryResolver返回上面的模拟存储库:

_mockRepositoryResolver
    .Setup(x => x.ResolveEstabAgeCategory())
    .Returns(_mockRepository.Object);

这是为了满足if (repository != null)健康)状况。

_mockRepository
    .Setup(x => x.InsertUpdateEstabAgeCategoryDetail(inventoryRequest.EstabAgeCategories))
    .ReturnsAsync(6);

接下来,您需要设置InsertUpdateEstabAgeCategoryDetail()模拟存储库上的方法返回一个值。该值由以下方式返回ProcessRequest()然后用来调用CreateResponse(inventoryRequest, result) as the result范围。

if (requestCount > 0 && resultCount < requestCount)
{
    handlerResult.IsSuccess = false;
    handlerResult.ErrorCode = (int)OTAErrorType.InvalidAgeCategory;
}
else if (requestCount > 0 || requestCount == resultCount)
{
    handlerResult.IsSuccess = true;
    handlerResult.ErrorCode = 0;
}

现在您可以查看CreateResponse方法并通过设置不同的值inventoryRequest.EstabAgeCategories并设置模拟_mockRepository.Setup(x => x.InsertUpdateEstabAgeCategoryDetail(inventoryRequest.EstabAgeCategories)).ReturnsAsync(6);要返回不同的值,可以通过满足不同的路径if陈述。

CreateResponse正在返回一个实例HandlerResult反过来又被返回Task<HandlerResult> Run。这是您想要对其进行断言的返回对象。

其中一个单元测试用例可能如下所示(我自己没有测试过):

[Fact]
public async Task GivenInventoryRequest_WhenRun_ThenHandlerResultReturned()
{
    // arrange
    var inventoryRequest = new InventoryRequest
    {
        EstabAgeCategories = new List<int>
        {
            1, 2, 3, 4, 5
        }
    };

    _mockRepository
        .Setup(x => x.InsertUpdateEstabAgeCategoryDetail(inventoryRequest.EstabAgeCategories))
        .ReturnsAsync(6);

    _mockRepositoryResolver
        .Setup(x => x.ResolveEstabAgeCategory())
        .Returns(_mockRepository.Object);

    // act
    var result = await _ageCategoryRequestHandler.Run(inventoryRequest);

    // assert
    _mockRepository
        .Verify(x => x.InsertUpdateEstabAgeCategoryDetail(inventoryRequest.EstabAgeCategories), Times.Once);
    
    Assert.True(result.Id == 0);
    Assert.True(result.ErrorCode == 0);
    Assert.False(result.IsSuccess);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Dot Net 核心应用程序的 Xunit 单元测试 的相关文章

  • CallContext.LogicalGet/SetData 的 .NET Core 等效项

    我正在尝试将使用 CallContext LogicalGet SetData 的现有 net 应用程序迁移到 net core 当 Web 请求到达应用程序时 我会在 CallContext 中保存一个 CorrelationId 并且每
  • Mediatr 范围问题

    我正在使用 Mediatr 处理来自队列的消息 我可以得到一个简单的例子来工作 但是 当我尝试将对象注入到我的处理程序中时 我遇到了问题 public class MessageCommandHandler IRequestHandler
  • 如何使用Dot net core WEB API实现文件上传?

    我正在开发 ASP DOT NET core Web api 我需要发送多个附件 我尝试如下
  • Azure Functions - 配置客户端证书身份验证

    函数是否支持通过使用客户端证书来授权对函数的访问消费计划 类似于所描述的方法here https learn microsoft com en us azure app service app service web configure t
  • 在project.json .Net Core中本地管理nuget

    我不想依赖 nuget 服务来下载依赖项 我想在我的 Net Core 应用程序中本地下载并使用 nuget 包 是否可以 方法与之前相同 打开您的NuGet config https docs nuget org consume nuge
  • 如何根据 ASP.NET VNEXT MVC6 中给出的路径进行虚拟路由/重定向?

    我有一个网站 它在不同的路径上公开多个 API 每个 API 由特定于应用程序部分的控制器处理 例如example com Api Controller Action param1 stuff 其中控制器发生变化 但操作保持相当一致 我有几
  • 从 appsettings.json 读取 JSON 对象

    TL DR 如何从 appsettings json 读取复杂的 JSON 对象 我有一个具有多种类型的配置值的 NET Core 2 x 应用程序 appsettings json看起来像下面的代码片段 我正在尝试读取的值ElasticS
  • HTTP按需触发azure函数多次调用自身

    我添加了http触发的azure函数并将其部署在函数应用程序中 函数应用程序仅包含一个此 http 按需触发器 azure 函数 功能应用程序有应用程序服务计划 而不是消费计划 另外 函数应用程序版本为 1 所以超时是无限的 在天蓝色的函数
  • 何时使用模拟框架?

    因此 我正在使用模拟框架 Moq 进行单元测试 并且想知道何时应该使用模拟框架 以下两个测试之间的优点 缺点是什么 public class Tests Fact public void TestWithMock Arrange var r
  • 从文件夹中删除文件的单元测试方法

    我们有一个方法 它将文件夹名称和天数作为参数 public void Delete string folder int days var files Directory GetFiles folder foreach var file in
  • 是否可以在 .NET Core 中将 gRPC 与 HTTP/1.1 结合使用?

    我有两个网络服务 gRPC 客户端和 gRPC 服务器 服务器是用 NET Core编写的 然而 客户端是托管在 IIS 8 5 上的 NET Framework 4 7 2 Web 应用程序 所以它只支持HTTP 1 1 https le
  • 注入的 HttpContext 始终为 null

    老实说 这太令人兴奋了 我无法让它发挥作用 无论注入到何处 上下文始终为空 我是否必须在 Startup cs 中添加上下文实例 如果是 怎么办 始发呼叫 services AddTransient
  • Azure函数无法读取应用程序设置和连接字符串

    我在 Azure 中创建了一个 HTTP 触发器函数 希望从 Azure SQL 数据库读取数据 我在函数应用程序的连接字符串部分配置了连接字符串 如下图所示 我使用下面的代码尝试读取连接字符串 var cnnString Configur
  • 发布 azure 函数并使用 appsettings.json

    我有一个 Azure Functions 项目 我使用 Visual Studio 2017 15 3 预览版 7 用 C 编写该项目 该函数项目包含两个单独的函数 这两个函数都是计时器触发的 我在 appsettings json 文件中
  • 如何在Azure Function的应用程序设置中定义providername属性

    我正在尝试在我的 Azure 函数中建立实体框架数据库连接 因此我需要在函数的应用程序设置中定义一个连接字符串 仅在 Azure 门户中添加一个以我的 DbContext 类名作为键的连接字符串会导致异常 因为连接到数据库时 provide
  • .net-core:ILDASM / ILASM 的等效项

    net core 是否有相当于 ILDASM ILASM 的功能 具体来说 我正在寻找在 Linux 上运行的东西 因此为什么是 net core ildasm 和 ilasm 工具都是使用此存储库中的 CoreCLR 构建的 https
  • 使用 python 将 CSV 文件上传到 Microsoft Azure 存储帐户

    我正在尝试上传一个 csv使用 python 将文件写入 Microsoft Azure 存储帐户 我已经发现C sharp https blogs msdn microsoft com jmstall 2012 08 03 convert
  • 使用最小起订量模拟第 3 方回调事件

    我们一直在尝试为用 C 编写的工作类编写单元测试 该类使用 moq 模拟第三方 API 基于 COM 来动态创建模拟对象 NUnit 是我们的单元测试框架 这个第三方组件实现了几个接口 但还需要使用事件回调到我们的工作类 我们的计划是模拟这
  • 如何解决asp.net core mvc项目中的“未找到视图”异常

    我正在尝试使用 VS Code 创建一个在 OSX 上运行的 ASP NET Core MVC 测试应用程序 访问默认主页 索引 或我尝试过的任何其他视图 时 我收到 未找到视图 异常 这是启动配置 public void Configur
  • 我可以使用 moq Mock 来模拟类而不是接口吗?

    正在经历https github com Moq moq4 wiki Quickstart https github com Moq moq4 wiki Quickstart 我看到它 Mock 一个接口 我的遗留代码中有一个没有接口的类

随机推荐

  • Socket.io + PhoneGap

    当我尝试使用时套接字IO https socket io with PhoneGap https phonegap com 我收到此错误 在 iOS 上应该支持 socket io Access Control Allow Origin 不
  • NSArray 填充 bool

    我正在尝试创建一个布尔值的 NSArray 请问我有多少人这样做 NSArray array NSArray alloc init array 0 YES 这对我不起作用 Thanks NSArray 不是 c 数组 您无法使用以下方式访问
  • ModelEntity.从 url 加载

    我有一个带有 AR 的屏幕 目前 usdz 3D 模型存储在应用程序本地 我们需要确保使用 get 请求接收它们 这是要检查的网址 https developer apple com augmented reality quick look
  • SQL 选择用字符串替换整数

    目标是将 SQL 查询中返回的整数值替换为该数字表示的 char 值 例如 标记为 Sport 的表属性被定义为 1 4 之间的整数值 1 篮球 2 曲棍球等 下面是数据库表 然后是所需的输出 数据库表 Player Team Sport
  • -webkit-transform 的替代方案:transformY?

    我正在创建一个 chrome 扩展 它在特定页面的顶部显示 iframe 该 iframe 被固定并放置在打开 body 标签之前 为了给这个 iframe 预留一个位置 我使用 CSS 向下移动主体 包括固定元素 webkit trans
  • AngularJS 中 !$pristine 与 $dirty 之间有什么区别

    最近我读了一些关于 angularJS 表单验证的教程 如下所示 p p 但我觉得 pristine and dirty是相等的 那么我可以使用下面的吗 p p 我认为这两个属性之间存在细微差别 这取决于您的用例 setDirty 将表单设
  • 如何获取node.js中的所有memcached数据?

    首先 我的目的是当用户关闭浏览器时用户会话数据应该过期 现在的问题是 我的服务器需要 memcached 才能正常工作 因此 我想从已关闭浏览器的 memcached 中删除该特定用户会话 我不想清除所有内存缓存 以便剩余用户的会话仍然存在
  • nvcc 和 NVIDIA-smi 显示的不同 CUDA 版本

    我对运行时显示的不同 CUDA 版本感到非常困惑which nvcc and nvidia smi 我在 ubuntu 16 04 上安装了 cuda9 2 和 cuda10 现在我将PATH设置为指向cuda9 2 所以当我跑步时 whi
  • 如何在 ASP.NET 应用程序中实现多语言服务器错误?

    我的 ASP NET Web 应用程序在 web config 中有以下部分
  • 从 Laravel 外部推送到 Laravel 队列 (NodeJS)

    我有一个 Laravel 5 3 安装作为纯 API 应用程序运行 需要从多个不同的应用程序进行连接 一切都工作正常 毕竟我们谈论的是 Laravel P 除了我不明白一件事 我有一个 MQTT 服务器 它正在侦听来自多个设备的消息 无论是
  • Node.js 的 Liquid 模板 [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有谁知道有没有港口液体模板 https github com tobi liquid对于 Node j
  • Logstash:Mutate { gsub ... } 不起作用

    mutate add field gt eee gt 2016 uaie gsub gt eee 2016 2015 这确实会创建一个字段 eee 但 gsub 会not更新它 为什么 add field 在底层过滤器成功时运行 在您的情况
  • 计算 DFFITS 作为回归中杠杆率和影响力的诊断

    我正在尝试手动计算 DFFITS 获得的值应该等于通过以下方式获得的第一个值dffits功能 不过我自己的计算肯定有问题 attach cars x1 lt lm speed dist data cars all observations
  • Firefox 是否有相当于 Chrome 的“translateZ(0);”强制GPU加速CSS动画?

    我有一个 CSS3 过渡 在 Chrome 中如丝绸般平滑 但在 Firefox 最新版本 中却不稳定 我知道我可以通过设置在 Chrome 中强制 GPU 加速 DOM 对象 webkit transform 翻译Z 0 on it 我可
  • 理解为什么弗洛伊德的龟兔赛跑算法在应用于整数数组时有效

    我试图解决这个leetcode问题https leetcode com problems find the duplicate number https leetcode com problems find the duplicate nu
  • 无法在 Windows 上使用 Redis 绑定 TCP 侦听器 *:6379

    我在 Windows 上使用 Redis 2 8 这是我从 github 版本下载的 解压后 我设置了 maxheapredis windows conf文件 运行后redis server redis windows conf I get
  • FFMpeg - 添加背景音乐

    这是我所拥有的 input1 avi 包含声音的视频 input2 avi 不包含声音的视频 music mp3 音频文件 我想向视频添加背景音乐 music mp3 文件 C input1 avi i C music mp3 shorte
  • Django Nginx X-Accel-Redirect 用于 Webfaction 上受保护的文件

    如果你想折磨某人直到时间结束 只需让他们配置 Django 和 Nginx X Accel Redirect 即可 这实际上是不可能的 我已经尝试了很多天了 我试图只允许在 webfaction 上使用 Nginx 从 django 中的登
  • 如何在“where value in...”子句中使用参数?

    当我只有一个状态代码作为参数时 这是有效的 当 parm list 中有多个 state code 时 如何使代码正常工作 要求 1 我不想在游标定义中对状态代码进行硬编码 2 我确实想在我的 where 子句中允许多个州代码 例如 我想运
  • Dot Net 核心应用程序的 Xunit 单元测试

    我最近开始学习单元测试 现在需要使用 Xunit 和 Moq 为 dot net core 应用程序编写单元测试 我可以编写一些非常基本的内容 但是当为复杂的类编写它们时 我有点陷入困境 下面是我将要为其编写测试的课程 public cla