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 单元测试 的相关文章

随机推荐

  • 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