返回顶部
首页 > 资讯 > 精选 >Net Core后端单元测试的实现方法
  • 471
分享到

Net Core后端单元测试的实现方法

2023-06-08 00:06:42 471人浏览 薄情痞子
摘要

这篇文章主要介绍了Net Core后端单元测试的实现方法,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。1. 前言单元测试一直都是"好处大家都知道很多,但是因为种种原

这篇文章主要介绍了Net Core后端单元测试的实现方法,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

1. 前言

单元测试一直都是"好处大家都知道很多,但是因为种种原因没有实施起来"的一个老大难问题。具体是否应该落地单元测试,以及落地的程度, 每个项目都有自己的情况。

本篇为个人认为"如何更好地写单元测试", 即更加 偏向实践向 中夹杂一些理论的分享。

下列示例的单元测试框架xUnit , Mock库为 Moq

2. 为什么需要单元测试

优点有很多, 这里提两点我个人认为的很明显的好处

2.1 防止回归

通常在进行新功能/模块的开发或者是重构的时候,测试会进行回归测试原有的已存在的功能,以验证以前实现的功能是否仍能按预期运行。

使用单元测试,可在每次生成后,甚至在更改一行代码后重新运行整套测试, 从而可以很大程度减少回归缺陷。

2.2 减少代码耦合

当代码紧密耦合或者一个方法过长的时候,编写单元测试会变得很困难。当不去做单元测试的时候,可能代码的耦合不会给人感觉那么明显。为代码编写测试会自然地解耦代码,变相提高代码质量和可维护性。

3. 基本原则和规范

 3.1 3A原则

3A分别是"arrange、act、assert", 分别代表一个合格的单元测试方法的三个阶段

  • 事先的准备

  • 测试方法的实际调用

  • 针对返回值的断言

一个单元测试方法可读性是编写测试时最重要的方面之一。 在测试中分离这些操作会明确地突出显示调用代码所需的依赖项、调用代码的方式以及尝试断言的内容.

所以在进行单元测试的编写的时候, 请使用注释标记出3A的各个阶段的, 如下示例

[Fact]public async Task VisitDataCompressExport_ShouldReturnEmptyResult_WhenFileTokenDoesNotExist(){  // arrange  var mockFiletokenStore = new Mock<IFileTokenStore>();  mockFiletokenStore    .Setup(it => it.Get(It.IsAny<string>()))    .Returns(string.Empty);  var controller = new StatController(    mockFiletokenStore.Object,    null);  // act  var actual = await controller.VisitDataCompressExport("faketoken");  // assert  Assert.IsType<EmptyResult>(actual);}

3.2 尽量避免直接测试私有方法

尽管私有方法可以通过反射进行直接测试,但是在大多数情况下,不需要直接测试私有的private方法, 而是通过测试公共public方法来验证私有的private方法。

可以这样认为:private方法永远不会孤立存在。更应该关心的是调用private方法的public方法的最终结果。

3.3 重构原则

如果一个类/方法,有很多的外部依赖,造成单元测试的编写困难。那么应该考虑当前的设计和依赖项是否合理。是否有部分可以存在解耦的可能性。选择性重构原有的方法,而不是硬着头皮写下去.

4 避免多个断言

如果一个测试方法存在多个断言,可能会出现某一个或几个断言失败导致整个方法失败。这样不能从根本上知道是了解测试失败的原因。

所以一般有两种解决方案

  • 拆分成多个测试方法

  • 使用参数化测试, 如下示例

[Theory][InlineData(null)][InlineData("a")]public void Add_InputNullOrAlphabetic_ThrowsArgumentException(string input){  // arrange  var strinGCalculator = new StringCalculator();  // act  Action actual = () => stringCalculator.Add(input);  // assert  Assert.Throws<ArgumentException>(actual);}

当然如果是对对象进行断言, 可能会对对象的多个属性都有断言。此为例外。

3.5 文件和方法命名规范 文件名规范

一般有两种。比如针对 UserController 下方法的单元测试应该统一放在 UserControllerTest 或者 UserController_Test

单元测试方法名

单元测试的方法名应该具有可读性,让整个测试方法在不需要注释说明的情况下可以被读懂。格式应该类似遵守如下

<被测试方法全名>_<期望的结果>_<给予的条件>// 例子[Fact]public void Add_InputNullOrAlphabetic_ThrowsArgumentException(){ ...}

4. 常用类库介绍

4.1 xUnit/MsTest/NUnit

编写.net core的单元测试绕不过要选择一个单元测试的框架, 三大单元测试框架中

  • MsTest是微软官方出品的一个测试框架

  • NUnit没用过

  • xUnit是.net Foundation下的一个开源项目,并且被dotnet GitHub上很多仓库(包括runtime)使用的单元测试框架

三大测试框架发展至今已是大差不差, 很多时候选择只是靠个人的喜好。

个人偏好 xUnit 简洁的断言

// xUnitAssert.True()Assert.Equal()// MsTestAssert.IsTrue()Assert.AreEqual()

客观地功能性地分析三大框架地差异可以参考如下

https://anarsolutions.com/automated-unit-testing-tools-comparison

4.2 Moq

官方仓库

Https://github.com/moq/moq4

Moq是一个非常流行的模拟库, 只要有一个接口它就可以动态生成一个对象, 底层使用的是Castle的动态代理功能.

基本用法

在实际使用中可能会有如下场景

public class UserController{  private readonly IUserService _userService;    public UserController(IUserService userService)  {    _userService = userService;  }    [HttpGet("{id}")]  public IActionResult GetUser(int id)  {    var user = _userService.GetUser(id);        if (user == null)    {      return NotFound();    }    else    {      ...    }  }}

在进行单元测试的时候, 可以使用 Moq_userService.GetUser 进行模拟返回值

[Fact]public void GetUser_ShouldReturnNotFound_WhenCannotFoundUser(){  // arrange  // 新建一个IUserService的mock对象  var mockUserService = new Mock<IUserService>();  // 使用moq对IUserService的GetUs方法进行mock: 当入参为233时返回null  mockUserService   .Setup(it => it.GetUser(233))   .Return((User)null);  var controller = new UserController(mockUserService.Object);    // act  var actual = controller.GetUser(233) as NotFoundResult;    // assert  // 验证调用过userService的GetUser方法一次,且入参为233  mockUserService.Verify(it => it.GetUser(233), Times.AtMostOnce());}

4.3 AutoFixture

官方仓库

https://github.com/AutoFixture/AutoFixture

AutoFixture是一个假数据填充库,旨在最小化3A中的 arrange 阶段,使开发人员更容易创建包含测试数据的对象,从而可以更专注与测试用例的设计本身。

基本用法

直接使用如下的方式创建强类型的假数据

[Fact]public void IntroductoryTest(){  // arrange  Fixture fixture = new Fixture();  int expectedNumber = fixture.Create<int>();  MyClass sut = fixture.Create<MyClass>();    // act  int result = sut.Echo(expectedNumber);    // assert  Assert.Equal(expectedNumber, result);}

上述示例也可以和测试框架本身结合,比如xUnit

[Theory, AutoData]public void IntroductoryTest(  int expectedNumber, MyClass sut){  // act  int result = sut.Echo(expectedNumber);    // assert  Assert.Equal(expectedNumber, result);}

5. 实践中结合Visual Studio的使用

Visual Studio提供了完备的单元测试的支持,包括运行. 编写. 调试单元测试。以及查看单元测试覆盖率等。

5.1 如何在Visual Studio中运行单元测试

5.2 如何在Visual Studio中查看单元测试覆盖率

如下功能需要Visual Studio 2019 Enterprise版本,社区版不带这个功能。

如何查看覆盖率

  • 在测试窗口下,右键相应的测试组 点

  • 点击如下的"分析代码覆盖率"

Net Core后端单元测试的实现方法

6. 实践中常见场景的Mock

主要

6.1 DbSet

使用EF Core过程中,如何mock DbSet是一个绕不过的坎。

方法一

参考如下链接的回答进行自行封装

https://stackoverflow.com/questions/31349351/how-to-add-an-item-to-a-mock-dbset-using-moq

Net Core后端单元测试的实现方法

方法二(推荐)

使用现成的库(也是基于上面的方式封装好的)

仓库地址:

https://github.com/romantitov/MockQueryable

使用范例

// 1. 测试时创建一个模拟的List<T>var users = new List<UserEntity>(){ new UserEntity{LastName = "ExistLastName", DateOfBirth = DateTime.Parse("01/20/2012")}, ...};// 2. 通过扩展方法转换成DbSet<UserEntity>var mockUsers = users.AsQueryable().BuildMock();// 3. 赋值给给mock的DbContext中的Users属性var mockDbContext = new Mock<DbContext>();mockDbContext .Setup(it => it.Users) .Return(mockUsers);

6.2 HttpClient

使用RestEase/Refit的场景

如果使用的是 RestEase 或者 Refit 等第三方库,具体接口的定义本质上就是一个interface,所以直接使用moq进行方法mock即可。

并且建议使用这种方式。

IHttpClientFactory

如果使用的是.Net Core自带的 IHttpClientFactory 方式来请求外部接口的话,可以参考如下的方式对 IHttpClientFactory 进行mock

https://www.thecodebuzz.com/unit-test-mock-httpclientfactory-moq-net-core/

6.3 ILogger

由于ILogger的LogError等方法都是属于扩展方法,所以不需要特别的进行方法级别的mock。

针对平时的一些使用场景封装了一个帮助类, 可以使用如下的帮助类进行Mock和Verify

public static class LoggerHelper{  public static Mock<ILogger<T>> LoggerMock<T>() where T : class  {    return new Mock<ILogger<T>>();  }  public static void VerifyLog<T>(this Mock<ILogger<T>> loggerMock, LogLevel level, string containMessage, Times times)  {    loggerMock.Verify(    x => x.Log(      level,      It.IsAny<EventId>(),      It.Is<It.IsAnyType>((o, t) => o.ToString().Contains(containMessage)),      It.IsAny<Exception>(),      (Func<It.IsAnyType, Exception, string>)It.IsAny<object>()),    times);  }  public static void VerifyLog<T>(this Mock<ILogger<T>> loggerMock, LogLevel level, Times times)  {    loggerMock.Verify(    x => x.Log(      level,      It.IsAny<EventId>(),      It.IsAny<It.IsAnyType>(),      It.IsAny<Exception>(),      (Func<It.IsAnyType, Exception, string>)It.IsAny<object>()),    times);  }}

使用方法

[Fact]public void Echo_ShouldLogInfORMation(){  // arrange  var mockLogger = LoggerHelpe.LoggerMock<UserController>();  var controller = new UserController(mockLogger.Object);    // act  controller.Echo();    // assert  mockLogger.VerifyLog(LogLevel.Information, "hello", Times.Once());}

7. 拓展

7.1 TDD介绍

TDD是测试驱动开发(Test-Driven Development)的英文简称. 一般是先提前设计好单元测试的各种场景再进行真实业务代码的编写,编织安全网以便将Bug扼杀在在摇篮状态。

Net Core后端单元测试的实现方法

此种开发模式以测试先行,对开发团队的要求较高, 落地可能会存在很多实际困难。详细说明可以参考如下

https://www.guru99.com/test-driven-development.html

感谢你能够认真阅读完这篇文章,希望小编分享的“Net Core后端单元测试的实现方法”这篇文章对大家有帮助,同时也希望大家多多支持编程网,关注编程网精选频道,更多相关知识等着你来学习!

--结束END--

本文标题: Net Core后端单元测试的实现方法

本文链接: https://lsjlt.com/news/250532.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Net Core后端单元测试的实现方法
    这篇文章主要介绍了Net Core后端单元测试的实现方法,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。1. 前言单元测试一直都是"好处大家都知道很多,但是因为种种原...
    99+
    2023-06-08
  • .NET Core单元测试的方法有哪些
    这篇文章主要介绍“.NET Core单元测试的方法有哪些”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“.NET Core单元测试的方法有哪些”文章能帮助大家解决问题。应用程序测试...
    99+
    2023-06-30
  • xUnit 编写 ASP.NET Core 单元测试的方法
    还记得 .NET Framework 的 ASP.NET WebForm 吗?那个年代如果要在 Web 层做单元测试简直就是灾难啊。.NET Core 吸取教训,在设计上考虑到...
    99+
    2022-06-07
    单元 ASP.NET 方法 xunit net 单元测试 core 测试 ASP
  • SpringBoot+TestNG单元测试的实现方法
    这篇文章主要讲解了“SpringBoot+TestNG单元测试的实现方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“SpringBoot+TestNG单元测试的实现方法”吧!目录背景接口测...
    99+
    2023-06-20
  • JunitMockito实现单元测试方法介绍
    目录一、前言二、JUnit 框架三、Mockito 框架3.1 使用 Mockito 创建 mock 对象3.2 使用 mock 对象实践单元测试3.3 使用 PowerMock m...
    99+
    2024-04-02
  • 如何使用xUnit为.net core程序进行单元测试
    这篇文章主要介绍“如何使用xUnit为.net core程序进行单元测试”,在日常操作中,相信很多人在如何使用xUnit为.net core程序进行单元测试问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何使...
    99+
    2023-06-19
  • 怎样使用xUnit为.net core程序进行单元测试
    怎样使用xUnit为.net core程序进行单元测试,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。一. 导读为什么要编写自动化测试程序(Automated Tests)?可以...
    99+
    2023-06-19
  • 测试TLS客户端的单元测试
    在Golang实战开发的过程中,我们经常会遇到一些这样那样的问题,然后要卡好半天,等问题解决了才发现原来一些细节知识点还是没有掌握好。今天编程网就整理分享《测试TLS客户端的单元测试》,聊聊,希望可...
    99+
    2024-04-04
  • django写单元测试的方法
       从网上找了很多django单元测试的案例,感觉不是很好用,于是自己写了一套测试方法,在测试环境我们只需要传uri 、请求方式、参数即可一键对所有接口进行...
    99+
    2024-04-02
  • SpringBoot+TestNG单元测试的实现
    目录背景接口测试用例,针对入参进行设计:言归正传!背景 由于开发任务进度紧张,接口及基础数据提供不全,即使设计全面的接口测试用例也无法全面有效的进行覆盖测试;且又因为单接口测试用例...
    99+
    2024-04-02
  • Android 单元测试的主要检测方法
      Android 单元测试 可以自检代码的准确性,避免重大错误流到后续工序中,也是编程的良好习惯。   Andorid 单元测试主要检测方法是否正确,主要步骤:   ...
    99+
    2022-06-06
    检测方法 单元 方法 单元测试 测试 Android
  • Hibernate单元测试怎么实现
    这篇文章主要介绍“Hibernate单元测试怎么实现”,在日常操作中,相信很多人在Hibernate单元测试怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Hibernate单元测试怎么实现”的疑惑有所...
    99+
    2023-06-17
  • SpringBoot单元测试如何实现
    这篇文章将为大家详细讲解有关SpringBoot单元测试如何实现,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。demo(SpringBoot 项目)被测试类:import org.springf...
    99+
    2023-06-25
  • android单元测试怎么实现
    Android单元测试可以通过使用JUnit框架和Android Testing Support Library来实现。以下是实现A...
    99+
    2023-08-29
    android
  • SpringBoot+JUnit5+MockMvc+Mockito单元测试的实现
    目录版本 项目结构 EchoServiceImpl EchoControllerNoMockitoTest EchoControllerMockTest 今天聊聊如何在 Spring...
    99+
    2024-04-02
  • 怎么实现Python的add5()单元测试
    本篇内容介绍了“怎么实现Python的add5()单元测试”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!TestAdd5类由unittest...
    99+
    2023-06-17
  • GO中的单元测试怎么实现
    这篇“GO中的单元测试怎么实现”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“GO中的单元测试怎么实现”文章吧。  ...
    99+
    2023-07-04
  • 在Android Studio中实现单元测试
      我们写了一个类,我们只希望测试下其算法是否正确,没必要真正运行一个完整的 APP,做单元测试即可。   在 Android Studio 中,我们在 java 文件夹...
    99+
    2022-06-06
    Android Studio studio 单元 单元测试 测试 Android
  • SpringBoot+TestNG单元测试怎么实现
    这篇“SpringBoot+TestNG单元测试怎么实现”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“SpringBoot+...
    99+
    2023-06-08
  • Node.js中怎么实现单元测试
    Node.js中怎么实现单元测试,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。为啥需要单元测试?所谓单元测试,就是对某个函数或者API进行正确性验证。来看个简单的例子add1....
    99+
    2023-06-17
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作