.Net单元测试xUnit和集成测试指南(1)

这篇具有很好参考价值的文章主要介绍了.Net单元测试xUnit和集成测试指南(1)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

引言

在现代化的软件开发中,单元测试集成测试是确保代码质量和可靠性的关键部分。ASP.NET Core 社区内提供了强大的单元测试框架,xUnit 是其中之一,它提供了简单、清晰和强大的测试功能,编写单元测试有许多优点;有助于回归、提供文档及辅助良好的设计。下面几节我们来深入浅出探讨如何使用 xUnit 进行 ASP.NET Core 应用程序的单元测试和集成测试。

内容大纲:

xUnit 简介

xUnit.net 是一个免费、开源、面向社区的.NET 单元测试工具。由 NUnit v2 的原始发明者编写,xUnit.net 是用于 C#F#(其他.NET 语言可能也可以使用,但不受支持)的最新技术单元测试。xUnit.net 可与 Visual StudioVisual Studio CodeReSharperCodeRushTestDriven.NET 一起使用。它是.NET 基金会的一部分,并遵守其行为准则。其许可协议为 Apache 2(为 OSI 批准的许可协议)。

xUnit.net 官方网站

创建单元测试项目

在单元测试中通常要遵循AAA模式,也就是 ArrangeActAssert,这是一种常见的测试组织结构。

  • Arrange(准备): 在这个阶段,将设置测试的前提条件,初始化对象、设置输入参数等。简单讲就是准备测试环境,确保被测代码在正确的上下文中执行。
  • Act(执行): 在这个阶段,会执行要测试的代码或方法。这是针对被测代码的实际调用或操作。
  • Assert: 在这个阶段,会验证被测代码的行为是否符合预期。检查实际结果与期望结果是否一致,如果不一致则测试失败。

示例:

[Fact]
public void Add_EmptyString_ReturnsZero()
{
    // Arrange
    var stringCalculator = new StringCalculator();

    // Act
    var actual = stringCalculator.Add("");

    // Assert
    Assert.Equal(0, actual);
}

可读性是编写单元测试最重要的方面之一,在测试中分离这些操作 都明确地突出调用代码所需的依赖项、调用代码的方式以及尝试断言的内容,让测试尽可能具有可读性。

好了理解了这个核心概念我们可以先创建项目一步步的练习了。

用 VS 创建单元测试项目

.Net单元测试xUnit和集成测试指南(1)

在项目创建完之后我们可以简单浏览一下 xUnit 单元测试项目装了那些 nuget 依赖,做到对项目有个简单的了解

  <ItemGroup>
    <PackageReference Include="coverlet.collector" Version="6.0.0" />
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
    <PackageReference Include="xunit" Version="2.5.3" />
    <PackageReference Include="xunit.runner.visualstudio" Version="2.5.3" />
  </ItemGroup>

下面我们创建一个简单的数据计算类。

  • 创建数学计算类
public class MathCalculator
{
    public int Add(int a, int b)
    {
        return a + b;
    }
}
  • 创建数据计算测试类
public class MathCalculatorTests
{
    [Fact]
    public void Add_TwoNumbers_ReturnSum()
    {
        // Arrange
        var calculator = new MathCalculator();

        // Act
        var result = calculator.Add(3, 5);

        // Assert
        Assert.Equal(8, result);
    }
}

测试一下,测试类库右键->运行测试

.Net单元测试xUnit和集成测试指南(1)

可以看到 我们的单元测试通过。

单元测试命名规范

本着代码自文档的原则,测试的名称建议应包括三个部分:

  • 要测试的方法的名称。
  • 测试的方案。
  • 调用方案时的预期行为。

示例

    [Fact]
    public void Add_TwoNumbers_ReturnSum()
    {
        // Arrange
        var calculator = new MathCalculator();

        // Act
        var result = calculator.Add(3, 5);

        // Assert
        Assert.Equal(8, result);
    }

要测试的方法名称是 MathCalculator 中的 Add 方法,测试的方案是传两个数,预期是返回两数之和 按照上面的测试名称的命名规则可以命名为Add_TwoNumbers_ReturnSum

单元测试最佳命名规范应该包括三个关键部分:要测试的方法的名称、测试的场景,以及调用该场景时的预期行为。良好的命名标准能清晰表达测试意图,提供有效文档,便于他人理解代码行为和快速定位问题。

单元测试最佳实践


将方法标记为测试方法在 xUnit 中有两个属性,FactTheory

Fact 属性

在方法上我们看到有一个 Attribute [Fact] ,[Fact] 属性是 xUnit 中最基本的测试属性之一,用于标记一个方法作为一个无需参数且不返回任何内容的测试方法。被标记为 [Fact] 的方法将会被 xUnit 框架识别并执行.

Theory 属性

Theory 属性用于标记一个测试方法,该方法可以接受参数并运行多次,每次运行时使用不同的参数值。Theory 属性通常用于数据驱动测试,允许在同一个测试方法中使用不同的输入数据进行测试.

InlineData 属性

[InlineData] 属性指定这些输入 Theory 标记的测试方法的参数值。

示例:

[Theory]
[InlineData(-1)]
[InlineData(0)]
[InlineData(1)]
public void IsPrime_ValuesLessThan2_ReturnFalse(int value)
{
    var result = _primeService.IsPrime(value);

    Assert.False(result, $"{value} should not be prime");
}

InlineData 适用于静态、硬编码的测试数据集合,适合于简单且固定的测试场景。

MemberData 属性

MemberData 属性是 xUnit 中用于数据驱动测试的一种方式,它允许从一个字段、属性或方法中获取测试数据,并将这些数据传递给测试方法进行多次测试。通过 MemberData 属性,可以更灵活地管理和提供测试数据,适用于需要动态生成测试数据的情况。

使用方式

  • 标记测试方法:使用 [Theory] 属性标记测试方法,以便接受从 MemberData 属性提供的测试数据。
  • 准备测试数据:创建一个公共静态字段、属性或方法,该字段、属性或方法返回一个 IEnumerable<object[]> 对象,其中每个 object[] 对象代表一组测试数据。
  • 传递测试数据:在 MemberData 属性中指定要使用的数据源,从而将数据传递给测试方法。

示例

    public static IEnumerable<object[]> GetComplexTestData()
    {
        yield return new object[] { 10, 5, 15 }; // 测试数据 1
        yield return new object[] { -3, 7, 4 }; // 测试数据 2
        yield return new object[] { 0, 0, 0 }; // 测试数据 3
        // 可以根据需要继续添加更多的测试数据
    }

   [Theory]
   [MemberData(nameof(GetComplexTestData))]
   public void Add_TwoNumbers_ReturnsSumofNumbers01(int first, int second, int sum)
   {
       // Arrange
       var calculator = new MathCalculator();

       // Act
       var result = calculator.Add(first, second);

       // Assert
       Assert.Equal(sum, result);
   }

MemberData 适用于动态、灵活的测试数据集合,适合于需要从外部源动态获取测试数据的情况。

.Net单元测试xUnit和集成测试指南(1)

自定义属性

除了上面提到的 InlineDataMemberData 之外还可以有更加灵活的方式继承DataAttribute实现自定义的Attribute

我们来做一个实现和上面一样的需求

  • 实现 Custom Attribute

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class CustomDataAttribute : DataAttribute
{

    private readonly int _first;
    private readonly int _second;
    private readonly int _sum;

    public CustomDataAttribute(int first, int second, int sum)
    {
        _first = first;
        _second = second;
        _sum = sum;
    }
    public override IEnumerable<object[]> GetData(MethodInfo testMethod)
    {
        yield return new object[] { _first, _second, _sum };
    }
}



  • 用例
   [Theory]
   [CustomData(1, 2, 3)]
   [CustomData(2, 3, 5)]
   public void Add_TwoNumbers_ReturnSum03(int num1, int num2, int expectedSum)
   {
       // Arrange
       var calculator = new MathCalculator();

       // Act
       var result = calculator.Add(num1, num2);

       // Assert
       Assert.Equal(expectedSum, result);
   }

自定义属性相较于使用 InlineDataMemberData 有以下优势:

  1. 灵活性:自定义属性允许您实现更复杂的逻辑来动态生成测试数据,可以从不同数据源中获取数据,实现更灵活的数据驱动测试。

  2. 重用性:通过自定义属性,您可以将相同的测试数据逻辑应用于多个测试方法,提高测试代码的重用性和可维护性。

  3. 可扩展性:自定义属性可以根据需求进行定制和扩展,适应不同的测试场景和数据需求,使得测试数据的生成更具灵活性。

  4. 可读性:通过自定义属性,可以使测试代码更具可读性和表达力,更清晰地表达测试数据的来源和意图。

尽管使用 InlineDataMemberData 可以满足大多数简单的测试数据需求,但当需要更复杂的数据生成逻辑、数据源、或者对测试数据进行处理时,使用自定义属性会更具优势,能够更好地满足个性化的测试需求。

在测试中应避免逻辑

[Theory]的出现就是为了避免我们在单元测试时编写一些额外的逻辑,造成测试之外的一些错误。

编写单元测试时,请避免手动字符串串联、逻辑条件(例如 if、while、for 和 switch)以及其他条件。

错误示范:

   [Fact]
   public void Add_TwoNumbers_ReturnsSumofNumbers02()
   {
       // Arrange
       var calculator = new MathCalculator();
       var testData = new List<(int, int, int)>
   {
       (1, 2, 3),
       (2, 3, 5),
       (3, 4, 7)
   };

       // Act & Assert
       foreach (var (first, second, sum) in testData)
       {
           var result = calculator.Add(first, second);
           Assert.Equal(sum, result);
       }
   }

此处用了 forEach 循环来批量断言,违反了单元测试的最佳实践。

测试中应避免逻辑的好处是:

  • 降低在测试中引入 bug 的可能性。
  • 专注于最终结果,而不是实现细节。

ITestOutputHelper 控制台输出

在 xUnit 中我们利用 Console.WriteLine输出时发现什么也不会显示,在 xUnit 单元测试项目中我们需要利用ITestOutputHelper
ITestOutputHelper是 xUnit 中的一个接口,用于在单元测试中输出信息。通过 ITestOutputHelper,您可以在测试运行时将调试信息、日志信息等输出到测试结果中,方便调试和查看测试过程中的输出信息。

调试

再要测试的方法上右键选择调试测试,或者点击方法上面的小点
.Net单元测试xUnit和集成测试指南(1)

最后

本篇文章简单的讲了单元测试的基础知识,让大家先对单元测试有个基本的概念,这些用在具体的项目中显然是不够的,后面的章节我们聊一下 TDD,Fake 管理,Log 日志输出,单元测试覆盖率,WebApi 的集成测试,DependencyInjection,Bogus,还有 Devops 的单元测试等知识。

本文完整源代码文章来源地址https://www.toymoban.com/news/detail-844119.html

到了这里,关于.Net单元测试xUnit和集成测试指南(1)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Wisej.NET 3.2.3 Crack 商业应用程序的Web开发构建迁移现代化工具

    Wisej.NET 3.2 adds new enterprise-grade features that simplify the development of complex Line of Business (LOB) cloud applications for the enterprise. Our goal is always to help improve developers productivity and make the applications using Wisej.NET more resilient and maintainable.   Getting Started The latest Wisej.NET 3.2 is available on NuGet. To use

    2024年02月16日
    浏览(54)
  • C# 使用xUnit进行单元测试

    目录 写在前面 操作步骤  执行结果 xUnit.net 是 NUnit 的作者Jim Newkirk搞的一个新的单元测试框架,目的是解决 NUnit 存在的一些问题和缺点,并在框架中加入一些最佳实践和扩展能力。 主要的改进点如下: 为每个测试方法产生一个对象实例 取消了 [SetUp] 和 [TearDown] 取消了 [Ex

    2024年02月04日
    浏览(30)
  • 自动化测试集成指南 -- 本地单元测试

    单元测试 (Unit Test) 是针对 程序的最小单元 来进行正确性检验的测试工作。程序单元是应用的最小可测试部件。一个单元可能是 单个程序、类、对象、方法 等。 如何区分单元测试和集成测试,一般情况下,单元测试应该不依赖数据库,网络,I/O和其他模块,否则就是集成测

    2024年02月16日
    浏览(51)
  • 工程化测试:Apollo的单元测试与集成测试指南

    「作者主页」 :雪碧有白泡泡 「个人网站」 :雪碧的个人网站 「推荐专栏」 : ★ java一站式服务 ★ ★ React从入门到精通 ★ ★ 前端炫酷代码分享 ★ ★ 从0到英雄,vue成神之路★ ★ uniapp-从构建到提升 ★ ★ 从0到英雄,vue成神之路 ★ ★ 解决算法,一个专栏就够了 ★ ★

    2024年02月06日
    浏览(28)
  • XUnit单元测试(实用项目)——看完不会用你打我

    xUnit.net 是针对 .NET 的免费、开源单元测试框架,可并行测试、数据驱动测试。测试项目需要同时引用 xUnit和被测试项目,从而对其进行测试。测试编写完成后,用 Test Runner 来测试项目,Test Runner 可以读取测试代码,并且知道所会使用的测试框架,然后执行,并显示结果。

    2024年02月04日
    浏览(35)
  • 掌握 xUnit 单元测试中的 Mock 与 Stub 实战

    上一章节介绍了 TDD 的三大法则,今天我们讲一下在单元测试中模拟对象的使用。 Fake - Fake 是一个通用术语,可用于描述 stub 或 mock 对象。 它是 stub 还是 mock 取决于使用它的上下文。 也就是说, Fake 可以是 stub 或 mock Mock - Mock 对象是系统中的 fake 对象,用于确定单元测试是

    2024年04月12日
    浏览(27)
  • Day956.代码现代化 -遗留系统现代化实战

    Hi,我是 阿昌 ,今天学习记录的是关于 代码现代化 的内容。 代码现代化的主要模式。 大体的脉络是这样的: 先对代码做可测试化重构,并添加测试; 在测试的保护下,安全地重构; 在测试的保护下,将代码分层。 先来看看 如何让代码变得可测 ,这是遗留系统现代化的

    2024年02月01日
    浏览(121)
  • Day960.架构现代化-微服务 -遗留系统现代化实战

    Hi,我是 阿昌 ,今天学习记录的是关于 架构现代化-微服务 的内容。 在 自治气泡模式 的基础上,通过 事件拦截 来实现 数据同步 ,给气泡和遗留系统之间又加上 API 访问 这个通信渠道。 这时的自治气泡就和真正的微服务差不多了。 有了这种模式,在开发一个全新的需求时

    2024年02月02日
    浏览(41)
  • 现代C++编程实战25-两个单元测试库:C++里如何进行单元测试

    你好,我是吴咏炜。 单元测试已经越来越成为程序员工作密不可分的一部分了。在 C++ 里,我们当然也是可以很方便地进行单元测试的。今天,我就来介绍两个单元测试库:一个是 Boost.Test [1],一个是 Catch2 [2]。 单元测试库有很多,我选择 Boost 的原因我在上一讲已经说过:“

    2024年02月07日
    浏览(34)
  • 《遗留系统现代化》读书笔记(基础篇)

    目录 为什么要对遗留系统进行现代化? 什么是遗留系统?  遗留系统的现代化价值 总结 遗留系统的四化建设 代码现代化 架构现代化 DevOps 现代化 团队结构现代化 总结 本文地址:《遗留系统现代化》读书笔记(基础篇)_陆业聪的博客-CSDN博客  你现在所写的每一行代码,

    2024年02月16日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包