首页 > 其他分享 >.net core 单元测试项目搭建

.net core 单元测试项目搭建

时间:2023-12-29 16:13:36浏览次数:42  
标签:core 场景 代码 单元测试 接口 测试 net 方法

背景和目的

为了提高系统稳定性,通常我们有两方面的计划:
  • 黑盒测试:自动化测试以接口来主体,通过控制入参的形式,检验出参,来模拟用户在线上的实际业务;(可以覆盖绝大部分的业务)
  • 白盒测试:单元测试以关键逻辑方法为主体,通过控制入参的形式,检验数据变化,站在开发的角度上来模拟实际调用(可以覆盖复杂方法,在黑盒测试中,很难测到的的数据变化)
ps:本篇主要介绍白盒测试,也就是代码层次的单元测试;

什么时候需要写单元测试

  1. 项目(必写) 开发方案阶段,应该整理出所有的核心业务点,针对核心业务点来规划需要写的单元测试;在实际开发的前中期,(比如前期把基础数据的建立后)开始编写核心方法,然后设计单元测试的场景,编写单元测试;
  2. 需求包(选写) 需求包中有复杂逻辑时,大家都觉得容易出错、不好测;
  3. 线上问题(选写) 复杂逻辑,可能该逻辑已经有单元测试了,但是线上问题完美避开了所有场景,单元测试中补充该场景以及类似场景; 复杂逻辑,可能是旧代码 或者 之前认为不复杂所以不必测试,补充单元测试;

哪些方法需要写单元测试

核心复杂逻辑,黑盒测试上难以测到的,同上;

如何覆盖尽可能多的场景

  1. 常规场景(happy pass)
    1. 业务1
    2. 业务2
    3. 业务3
  2. 边界场景 :徘徊在边界上的入参或数据条件,依旧能得到相应的结果;
  3. 异常场景 :超出边界之外的入参或数据条件,判断异常达到预期;
总体上来讲,可以分为常规、边界、异常三种套路,每种套路依据实际业务场景可以验证多种结果,毕竟实际业务可能不止一种常规结果;  

如何写单元测试

  1. 优化方法,明确方法的含义; 如果方法已存在在先,想对它写单元测试,首先得确保该方法有以下特点:
    1. 语义化:单独看这个方法,有明确的含义,功能单一;
    2. 入参出参明确;
    3. 去掉不必要测试的代码范围:1)入库相关,比如sql、redis、mq、es;2)远端调用;
  2. 写单元测试 一般的代码步骤:
    1. 声明已知数据;
    2. 模拟无需测试的接口方法;
    3. 调同需要测试的接口方法;
    4. 检验数据变化是否符合预期;
模拟接口会带来巨量的工作量,而且大部分工作量是低效且无需测试的,所以在写代码测试的时候,首先要优化方法,然后推荐用注入的方式来测试,避开需要模拟非必要接口方法的情况;

与开发和发布流程闭环

1、开发 开发过程中随时都可以在IDE跑单元测试,右键项目、类、测试方式都可以跑单元测试

2、发布 Jenkins中可以集成单元测试环节,当我们去发布的时候首先会去跑单元测试项目,只有当单元测试都通过时,才会继续发布;当单元测试未通过,可以通知IM消息通知群里的链接点进去,查看失败的用例,修复代码并重新发布;

 

如何搭建单元测试项目

1、选择合适的单元测试框架

https://zhuanlan.zhihu.com/p/644833761

推荐使用Xunit,原因无非是支持的扩展包比较多,功能全,使用起来比较方便;

2、注入实例

注入实例的原因在于,已有项目的接口通常在构造函数里有大量的注入,如果我们要实例化该接口的话,就要mock它所依赖的所有注入接口,如果构造函数里有几十个依赖的接口,那想测试该接口将会变得异常困难,

所以我们主要需要解决的问题就是注入问题,让我们写单元测试的时候跟写一半业务代码一样简单;

 大体的注入思想是:

① 自定义接口(比如IxxxService,IxxxRepo)复用原有项目的注入,最好是提取出来同一个文件,给api project和单元测试 project能复用,避免两边改;

②数据库ef上下文、redis、mq、es、cap等等中间件,坚持一个原因:能进内存的就进内存;

这些组件都是支持注册进内存的,网上查一下很简单就能配置;

进内存的意义在于,虽然我们不建议测这些中间件相关的代码,但是万一无意执行到了不会无端报错,另外如果真的要测到经过这些中间件的代码时,也是可以支持的,因为数据放在内存里也是可以承载的;

③原生sql如何支持

如果万不得已,要测到原生sql时,官方只支持sqlite,改成sqlite注册为本地文件就可以了;

 

 

但是有一个问题,我们代码里可能都没写库名以及schma,当我们有多个dbcontext,而且dataset还交互存在时,就会不可避免的报错了,这里就没办法不动源代码了,目前看来用sqlsugar来改造源代码,避免使用dbcontext才能根本上解决吧;

3、单元测试startup

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

xunit 单元测试项目引用这些就可以跟api项目一样配置startup文件了,ConfigureServices 、Configure、ConfigureHost都能一样写了;

如果想使用配置文件的话,使用ConfigureHost就可以搞定了;为啥用使用不同配置,比如本地和线上的数据库连接不是同一个,等等各种原因都需要线上线下使用不同配置;

 4、为啥很少用mock

就像第2步注入实例里说的,实例化一个接口,需要mock它依赖的所有或部分接口,使用起来非常麻烦,而且我们说单元测试的目的是测试核心方法,并不是去像白盒测试(自动化测试)一样去测试整个流程,

所以我们通常测的方法都是纯逻辑,方法功能单一,入参和出参明确,所以我们想要跟写业务代码一样简单来写单元测试,测试那些复杂逻辑是否有漏洞;

 

 

 

 

 

   

标签:core,场景,代码,单元测试,接口,测试,net,方法
From: https://www.cnblogs.com/willardzmh/p/17934594.html

相关文章

  • MMGCN: Multi-modal Graph Convolution Network for Personalized Recommendation of
    目录概符号说明MMGCN代码WeiY.,WangX.,NieL.,HeX.,HongR.andChuaT.MMGCN:Multi-modalgraphconvolutionnetworkforpersonalizedrecommendationofmicro-video.MM,2019.概推荐领域里比较早的多模态方法.符号说明\(\mathcal{U}\),userset;\(\mathc......
  • Taurus .Net Core 微服务开源框架:Admin 插件【4-8】 - 配置管理-Mvc【Plugin-Limit 接
    前言:继上篇:Taurus.NetCore微服务开源框架:Admin插件【4-7】-配置管理-Mvc【Plugin-Metric接口调用次数统计】本篇继续介绍下一个内容:1、系统配置节点:Mvc- Plugin-Limit接口访问限制、IP限制、Ack限制:配置界面如下:限制目前提供以下三个类别的限制:1、Rate访......
  • .NET批量更新两种方式性能对比
    数据库MySql,.NET7,ORMEF使用新的批量更新:publicasyncTaskUpdateManyAsync(stringurl,stringdata){await_dbContext.TestDb.Where(a=>a.Url!=null&&a.Url.Equals(url)).ExecuteUpdateAsync(a=>a.SetProperty(u=>u.TestDate,data));returntrue......
  • 代码整洁之道:边界、单元测试、类
    来源:博客园(作者-BNDong)边界边界上的代码需要清晰的分割和定义了期望的测试。应该避免我们的代码过多地了解第三方代码中的特定信息。依靠你能控制的东西,好过依靠你控制不了的东西,免得日后受它控制。单元测试TDD三定律在编写不能通过的单元测试前,不可编写生成代码......
  • 在不受支持的 Mac 上安装 macOS Sonoma (OpenCore Legacy Patcher)
    在不受支持的Mac上安装macOSSonoma、Ventura、Monterey、BigSur(OpenCoreLegacyPatcher)InstallmacOSonunsupportedMacs作者主页:sysin.orgmacOSSonoma正式版已发布,OpenCoreLegacyPatcherv1.0.0版本已支持。随着OpenCoreLegacyPatcher1.0.0的发布,OLP项目组......
  • linux下java调用netcore程序
    代码备份仅供参考自述文件#JavaCallCSharpJavacallC#libbuildwith.NETCORE2.0viaC++aswraperThecodeisbasedon[examplefromcoreCLR](https://github.com/dotnet/coreclr/tree/master/src/coreclr/hosts/unixcoreruncommon)JavausingJNItocallC++......
  • Linux下netcore调用java代码
    代码备份,仅供参考自述文件#CSharpCallJavaC#invokeJavaviaC++asawraper.C#invokeC++viaP/invoke.C++startsaJVMtoruntheJavacode.C#codeshouldbecompiledin.NETcore2.0YoushouldedittheMakefiletosetthePathofJavaSDKexpor......
  • Failed to load resource: net::ERR_INCOMPLETE_CHUNKED_ENCODING。
    前端间隔性报错:后端接口异常浏览器审查,内容如下:前端报错:Failedtoloadresource:net::ERR_INCOMPLETE_CHUNKED_ENCODING。 后端报错:Causedby:java.io.IOException:Brokenpipeatsun.nio.ch.FileDispatcherImpl.write0(NativeMethod)atsun.nio.ch.SocketDi......
  • Asp.net WebApi Swagger Tag 标记分组归纳显示Api接口路由
    官方文档说明地址https://swagger.io/docs/specification/2-0/grouping-operations-with-tags/创建一个自定义的特性类publicclassControllerGroupAttribute:Attribute{publicControllerGroupAttribute(stringgroupName){if......
  • 【dotnet】啥?这家伙写gRpc 居然没有pb文件
    使用.NET的代码优先gRPC服务和客户端当整个系统使用.NET时,代码优先是一个不错的选择:可以在.NET服务器和客户端之间共享.NET服务和数据协定类型。无需在 .proto 文件和代码生成过程中定义协定。不建议在具有多种语言的polyglot系统中使用代码优先。.NET服务......