自动化测试数据生成:Asp.Net Core单元测试利器AutoFixture详解

asp,net,core,autofixture · 浏览次数 : 0

小编点评

**Test_DisableAutoProperties() 方法测试用例** 该测试用例使用 AutoFixture 进行单元测试,测试 `Test_DisableAutoProperties()` 方法,该方法用于模拟一个对象的属性值为默认值的设置情况。 **测试步骤:** 1. 创建一个 `Fixture` 实例。 2. 使用 `OmitAutoProperties()` 方法禁用自动属性设置。 3. 创建一个 `Staff` 对象。 4. 检查 `sut.Id`、`sut.Name`、`sut.Email`、`sut.Age`、`sut.Addresses` 和 `sut.Created` 属性是否为 `null`。 5. 执行 `Do()` 方法,执行自定义操作。 6. 验证期望属性值是否与实际属性值相匹配。 **测试用例代码:** ```csharp [Fact] public void Test_DisableAutoProperties() { // Arrange var fixture = new Fixture(); var sut = fixture.Build(); // Assert Assert.Equal(0, sut.Id); Assert.Null(sut.Name); Assert.Null(sut.Email); Assert.Null(sut.Age); Assert.Null(sut.Addresses); Assert.Null(sut.Created); } ``` **测试说明:** 1. `fixture.Build()` 创建一个 `Staff` 对象。 2. `sut.Id`、`sut.Name`、`sut.Email`、`sut.Age`、`sut.Addresses` 和 `sut.Created` 属性的默认值设置为 `null`。 3. `fixture.OmitAutoProperties()` 方法禁用自动属性设置。 4. `fixture.Create()` 创建一个新的 `Staff` 对象。 5. `Assert.Equal()` 检查 `sut.Id`、`sut.Name`、`sut.Email`、`sut.Age`、`sut.Addresses` 和 `sut.Created` 属性的值是否与预期值相匹配。 **注意:** 1. `fixture.Customize(new AutoMoqCustomization())` 用于定制 `Staff` 对象的属性值。 2. `ReturnsUsingFixture()` 方法用于手动设置方法的行为。

正文

引言

在我们之前的文章中介绍过使用Bogus生成模拟测试数据,今天来讲解一下功能更加强大自动生成测试数据的工具的库"AutoFixture"

什么是AutoFixture?

AutoFixture 是一个针对 .NET 的开源库,旨在最大程度地减少单元测试中的“安排(Arrange)”阶段,以提高可维护性。它的主要目标是让开发人员专注于被测试的内容,而不是如何设置测试场景,通过更容易地创建包含测试数据的对象图,从而实现这一目标。

AutoFixture 可以帮助开发人员自动生成测试数据,减少手动设置测试数据的工作量,提高单元测试的效率和可维护性。通过自动生成对象,开发人员可以更专注于编写测试逻辑,而不必花费大量精力在准备测试数据上。

其实和Bogus相比,AutoFixture更强大的地方在于可以自动化设置对象的值,当类发生变化时如属性名或者类型更改,我们不需要去进行维护,AutoFixture可以自动适应Class的变化。

AutoFixture与流行的 .NET 测试框架(如 NUnitxUnit)可以无缝集成。

AutoFixture实战

我们在创建xUnit单元测试项目dotNetParadise.AutoFixture

安装依赖

创建完项目之后我们首先要安装Nuget

PM> NuGet\Install-Package AutoFixture -Version 4.18.1

初始化

AutoFixture的使用是从一个Fixture的实例对象开始的

var fixture = new Fixture();

接下来我们先创建一个测试类来学一下AutoFixture的使用

public class AutoFixtureStaffTest
{
    private readonly IFixture _fixture;
    public AutoFixtureStaffTest()
    {
        _fixture = new Fixture();
    }
}

实战

我们之前的测试项目创建了Sample.ApiSample.Repository两个类库来做我们被测试的项目,本章继续使用Sample.Repository来演示AutoFixture的使用。

dotNetParadise.AutoFixture 测试项目添加Sample.Repository的项目引用

Sample.Repository中我们有一个Staff的实体对象,继续用作我们的测试

public class Staff
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Email { get; set; }
    public int? Age { get; set; }
    public List<string>? Addresses { get; set; }
    public DateTimeOffset? Created { get; set; }
    public void Update(Staff staff)
    {
        this.Name = staff.Name;
        this.Email = staff.Email;
        this.Age = staff.Age;
        this.Addresses = staff.Addresses;
        Created = staff.Created;
    }
}

属性赋值

   [Fact]
   public void Staff_SetProperties_ValuesAssignedCorrectly()
   {
       //Arrange
       Staff staff = new Staff();
       //生成Int类型
       staff.Id = _fixture.Create<int>();
       //生成string 类型
       staff.Name = _fixture.Create<string>();
       //生成DateTimeOffset类型
       staff.Created = _fixture.Create<DateTimeOffset>();
       //生成 List<string>?
       staff.Addresses = _fixture.CreateMany<string>(Random.Shared.Next(1, 100)).ToList();
       //Act
       //...省略
       // Assert
       Assert.NotNull(staff); // 验证 staff 对象不为 null

       // 验证 staff.Id 是 int 类型
       Assert.IsType<int>(staff.Id);

       // 验证 staff.Name 是 string 类型
       Assert.IsType<string>(staff.Name);

       // 验证 staff.Created 是 DateTimeOffset? 类型
       Assert.IsType<DateTimeOffset>(staff.Created);

       // 验证 staff.Addresses 是 List<string> 类型
       Assert.IsType<List<string>>(staff.Addresses);

       // 验证 staff.Addresses 不为 null
       Assert.NotNull(staff.Addresses);

       // 验证 staff.Addresses 中的元素数量在 1 到 100 之间
       Assert.InRange(staff.Addresses.Count, 1, 100);
   }

示例中用到 AutoFixture 提供的的方法随机分配随机值,上面的示例中用到使用到了两个方法

Create<T>方法

  • 用于生成一个指定类型 T 的实例。它会自动填充对象的属性和字段,以便创建一个完整的对象实例。
  • 这个方法通常用于生成单个对象实例,适用于需要单个对象作为测试数据的情况。
  • 当调用 Create<T> 方法时,AutoFixture 会根据 T 类型的构造函数、属性和字段来自动生成合适的值,以确保对象实例的完整性和一致性。

CreateMany<T>方法

  • 用于生成多个指定类型 T 的实例,通常用于生成集合或列表类型的测试数据。
  • 这个方法允许你指定要生成的实例数量,并返回一个包含这些实例的 IEnumerable 集合。
  • 当调用 CreateMany<T> 方法时,AutoFixture 会根据 T 类型的构造函数、属性和字段来生成指定数量的对象实例,以便填充集合或列表。

T包括基本类型(如 stringint)、自定义对象等

Create<T>构造对象

上面的例子我们自己实例化的对象然后对对象挨个赋值,目的是让大家对AutoFixture的使用有一个初步的认识,上面也解释到了Create<T>的泛型参数T可以是自定义的对象,那么我们来简化一下上面的示例

[Fact]
public void Staff_ObjectCreation_ValuesAssignedCorrectly()
{
    // Arrange
    Staff staff = _fixture.Create<Staff>(); // 使用 AutoFixture 直接创建 Staff 对象

    // Act
    //...省略

    // Assert
    Assert.NotNull(staff); // 验证 staff 对象不为 null

    // 验证 staff.Id 是 int 类型
    Assert.IsType<int>(staff.Id);

    // 验证 staff.Name 是 string 类型
    Assert.IsType<string>(staff.Name);

    // 验证 staff.Created 是 DateTimeOffset? 类型
    Assert.IsType<DateTimeOffset>(staff.Created);

    // 验证 staff.Addresses 是 List<string> 类型
    Assert.IsType<List<string>>(staff.Addresses);

    // 验证 staff.Addresses 不为 null
    Assert.NotNull(staff.Addresses);

    // 验证 staff.Addresses 中的元素数量在 1 到 100 之间
    Assert.InRange(staff.Addresses.Count, 1, 100);
}

修改后的例子中,我们使用 AutoFixtureCreate<Staff>() 方法直接创建了一个 Staff 对象,而不是手动为每个属性赋值。这样可以更简洁地生成对象实例。

数据驱动测试

在正常的同一个测试方法中使用不同的输入数据进行测试时,通常都是基于 Theory 属性配合InlineData或者MemberData来完成的,有了AutoFixture之后数据也不用我们自己造了,来看一下实战入门

第一步Nuget安装依赖

PM> NuGet\Install-Package AutoFixture.Xunit2 -Version 4.18.1

[AutoData]属性

[Theory, AutoData]
public void Staff_Constructor_InitializesPropertiesCorrectly(
    int id, string name, string email, int? age, List<string> addresses, DateTimeOffset? created)
{
    // Act
    var staff = new Staff { Id = id, Name = name, Email = email, Age = age, Addresses = addresses, Created = created };

    // Assert
    Assert.Equal(id, staff.Id);
    Assert.Equal(name, staff.Name);
    Assert.Equal(email, staff.Email);
    Assert.Equal(age, staff.Age);
    Assert.Equal(addresses, staff.Addresses);
    Assert.Equal(created, staff.Created);
}

通过 AutoData 方法,测试方法的参数化设置变得更加简单和高效,使得编写参数化测试方法变得更加容易。

[InlineAutoData]属性

如果我们有需要提供的特定化参数,可以用[InlineAutoData]属性,具体使用可以参考如下案例

    [Theory]
    [InlineAutoData(1)]
    [InlineAutoData(2)]
    [InlineAutoData(3)]
    [InlineAutoData]
    public void Staff_ConstructorByInlineData_InitializesPropertiesCorrectly(
     int id, string name, string email, int? age, List<string> addresses, DateTimeOffset? created)
    {
        // Act
        var staff = new Staff { Id = id, Name = name, Email = email, Age = age, Addresses = addresses, Created = created };

        // Assert
        Assert.Equal(id, staff.Id);
        Assert.Equal(name, staff.Name);
        Assert.Equal(email, staff.Email);
        Assert.Equal(age, staff.Age);
        Assert.Equal(addresses, staff.Addresses);
        Assert.Equal(created, staff.Created);
    }

自定义对象属性值

AutoFixtureBuild 方法结合 With 方法可以用于自定义对象的属性值

    [Fact]
    public void Staff_SetCustomValue_ShouldCorrectly()
    {
        var staff = _fixture.Build<Staff>()
            .With(_ => _.Name, "Ruipeng")
            .Create();
        Assert.Equal("Ruipeng", staff.Name);
    }

禁用属性自动生成

AutoFixture 中,可以使用 OmitAutoProperties 方法来关闭自动属性生成,从而避免自动生成属性值。这在需要手动设置所有属性值的情况下很有用。

    [Fact]
    public void Test_DisableAutoProperties()
    {
        // Arrange
        var fixture = new Fixture();
        var sut = fixture.Build<Staff>()
                         .OmitAutoProperties()
                         .Create();

        // Assert
        Assert.Equal(0, sut.Id); // 验证 Id 属性为默认值 0
        Assert.Null(sut.Name); // 验证 Name 属性为 null
        Assert.Null(sut.Email); // 验证 Email 属性为 null
        Assert.Null(sut.Age); // 验证 Age 属性为 null
        Assert.Null(sut.Addresses); // 验证 Addresses 属性为 null
        Assert.Null(sut.Created); // 验证 Created 属性为 null
    }

Do 方法执行自定义操作

Do 方法是 AutoFixture 中用于执行操作的方法,通常结合 Build 方法一起使用,用于在构建对象时执行自定义操作。让我详细解释一下 Do 方法的用法和作用:

主要特点:

  • 执行操作:Do 方法允许在对象构建过程中执行自定义操作,例如向集合添加元素、设置属性值等。
  • 链式调用:可以通过链式调用多个 Do 方法,依次执行多个操作。
  • 灵活定制:通过 Do 方法,可以在对象构建过程中灵活地定制对象的属性值或执行其他操作。
    使用方法:
  • 结合 Build 方法:通常与 Build 方法一起使用,用于为对象构建器执行操作。
  • 执行自定义操作:在 Do 方法中传入一个 lambda 表达式,可以在 lambda 表达式中执行需要的操作。
  • 链式调用:可以多次调用 Do 方法,实现多个操作的顺序执行。
   [Fact]
   public void Test_UpdateMethod()
   {
       // Arrange
       var fixture = new Fixture();
       var staff1 = fixture.Create<Staff>();
       var staff2 = fixture.Create<Staff>();

       // 使用 Do 方法执行自定义操作
       var staff3 = fixture.Build<Staff>()
                                 .Do(x => staff1.Update(staff2))
                                 .Create();

       // Assert
       Assert.Equal(staff2.Name, staff1.Name); // 验证 Name 是否更新
       Assert.Equal(staff2.Email, staff1.Email); // 验证 Email 是否更新
       Assert.Equal(staff2.Age, staff1.Age); // 验证 Age 是否更新
       Assert.Equal(staff2.Addresses, staff1.Addresses); // 验证 Addresses 是否更新
       Assert.Equal(staff2.Created, staff1.Created); // 验证 Created 是否更新
   }

创建三个对象,在第三个创建过程中把第一个的对象属性用第二个对象的属性覆盖。

Customize Type 自定义类型

使用自定义类型构建器来执行复杂的初始化,并且保证了创建多个相同的实例中要保持一致的自定义行为。

首先我们可以在我们的测试类构造函数中定义一个自定义规则

    public AutoFixtureStaffTest()
    {
        _fixture = new Fixture();
        _fixture.Customize<Staff>(composer => composer.With(x => x.Email, "zhangsan@163.com"));
    }

比如我设置了所有的 email 都叫zhangsan@163.com

    [Fact]
    public void Test_StaffNameIsJohnDoe()
    {
        // Arrange
        Staff staff = _fixture.Create<Staff>();

        // Act

        // Assert
        Assert.Equal("zhangsan@163.com", staff.Email);
    }

这个位置大概得思想就是这样,保证用到的多实例都有相同的行为,可以参考:
使用 AutoFixture 自定义类型的生成器

Auto-Mocking with Moq

第一步安装Nuget

PM> NuGet\Install-Package AutoFixture.AutoMoq -Version 4.18.1

    [Fact]
    public async Task Repository_Add_ShouleBeSuccess()
    {
        _fixture.Customize(new AutoMoqCustomization());
        var repoMock = _fixture.Create<IStaffRepository>();
        Assert.NotNull(repoMock);
    }

创建 Fixture 实例并使用 AutoMoqCustomization 进行定制化,以便自动模拟 Moq 对象。
使用 Create<IInterface>() 方法创建一个可分配给 IInterface 接口的模拟实例。

Auto-configured Mocks

官网示例:

fixture.Customize(new AutoMoqCustomization { ConfigureMembers = true });
fixture.Inject<int>(1234);

var document = fixture.Create<IDocument>();
Console.WriteLine(document.Id); // 1234

当将 ConfigureMembers = true 添加到 AutoMoqCustomization 中时,不仅会作为自动模拟容器,还会自动配置所有生成的模拟对象,使其成员返回 AutoFixture 生成的值。
使用 Inject<int>(1234) 将整数值 1234注入到 Fixture 中。
使用 Create<IDocument>() 创建一个 IDocument 接口的实例,并输出其 Id 属性值。

更多

Moq 框架中存在一些限制,其中自动配置模式无法设置具有 ref参数的方法,并且也无法配置泛型方法。然而,您可以使用 ReturnsUsingFixture 扩展方法轻松地设置这些方法。

官网示例:

converter.Setup(x => x.Convert<double>("10.0"))
         .ReturnsUsingFixture(fixture);

在这个示例中,使用 ReturnsUsingFixture 扩展方法手动设置了一个名为 Convert 的泛型方法的行为。
当调用 Convert 方法并传入字符串"10.0" 时,ReturnsUsingFixture方法将使用fixture生成的值作为返回值。 通过使用ReturnsUsingFixture扩展方法,您可以绕过Moq框架的限制,手动设置具有ref` 参数或泛型方法的行为,以满足特定的测试需求.

最后

AutoFixture就像是一个自动数据生成器,让我们的单元测试变得更简单、更高效。通过使用它,我们可以轻松地创建测试数据,专注于写好测试逻辑,而不用为数据准备的琐事烦恼.

😄欢迎关注笔者公众号一起学习交流,获取更多有用的知识~
image

与自动化测试数据生成:Asp.Net Core单元测试利器AutoFixture详解相似的内容:

自动化测试数据生成:Asp.Net Core单元测试利器AutoFixture详解

引言 在我们之前的文章中介绍过使用Bogus生成模拟测试数据,今天来讲解一下功能更加强大自动生成测试数据的工具的库"AutoFixture"。 什么是AutoFixture? AutoFixture 是一个针对 .NET 的开源库,旨在最大程度地减少单元测试中的“安排(Arrange)”阶段,以提高

ASP.NET 6启动时自动创建MongoDB索引

最近,在使用MongoDB时,碰到这样的一个需求:针对某个Collection手动在开发环境创建了索引,但在测试环境和生产环境不想再手动操作了,于是就想着干脆通过代码的方式在ASP.NET 6应用启动时自动创建,如果是重复创建则直接跳过。

.NET单元测试使用AutoFixture按需填充的几种方式和最佳实践

AutoFixture是一个.NET库,旨在简化单元测试中的数据设置过程。通过自动生成测试数据,它帮助开发者减少测试代码的编写量,使得单元测试更加简洁、易读和易维护。AutoFixture可以用于任何.NET测试框架,如xUnit、NUnit或MSTest。 默认情况下AutoFixture生成的字

《最新出炉》系列入门篇-Python+Playwright自动化测试-40-录制生成脚本

1.简介 各种自动化框架都会有脚本录制功能, playwright这么牛叉当然也不例外。很早之前的selenium、Jmeter工具,发展到每种浏览器都有对应的录制插件。今天我们就来看下微软自动化框架playwright是如何录制脚本的。很多小伙伴或者童鞋们会觉得奇怪,怎么现在才将录制生成脚本啊,要

利用ChatGPT提升测试工作效率——测试工程师的新利器(一)

在测试工作中可以辅助功能测试包括需求分析或解读代码(注意代码安全)后生成测试用例,还可以辅助生成代码,接口测试用例,自动化脚本等各个方向起作用。当然实际使用中可能会因为提示词的不同生成的结果需要人工多次对话训练才可以。但是使用chatGPT肯定比不用能提高工作效率。当然具体落地后如何进行量化提效抽象...

《最新出炉》系列入门篇-Python+Playwright自动化测试-41-录制视频

1.简介 上一篇讲解和分享了录制自动生成脚本,索性连带录制视频也一股脑的在这里就讲解和分享了。今天我们将学习如何使用Playwright和Python来录制浏览器操作的视频,以便在需要时进行回放和分析。 2.录制视频语法 录制视频介绍官方API的文档地址:https://playwright.dev

精准测试之过程与实践

精准测试的核心组件包含的软件测试示波器、用例和代码的双向追溯、智能回归测试用例选取、覆盖率分析、缺陷定位、测试用例聚类分析、测试用例自动生成系统,这些功能完整的构成了精准测试技术体系。

《最新出炉》系列入门篇-Python+Playwright自动化测试-47-自动滚动到元素出现的位置

1.简介 在我们日常工作中或者生活中,经常会遇到我们的页面内容较多,一个屏幕范围无法完整展示内容,我们就需要滚动滚动条去到我们想要的地方,如下图页面,我们虽然在豆瓣首页,但是内容并不完整,如果我们想要直接点击电影模块中的选电影按钮,是需要往下滑动的。当页面超过屏幕的高度时候,需要滚动到元素出现的位置

Apifox:成熟的测试工具要学会自己写接口文档

好家伙, 在开发过程中,我们总是避免不了进行接口的测试, 而相比手动敲测试代码,使用测试工具进行测试更为便捷,高效 今天发现了一个非常好用的接口测试工具Apifox 相比于Postman,他还拥有一个非常nb的功能, 在接口的测试完成后,它可以一键生成接口文档 下载地址(免费哟): Apifox -

OpenSSL 生成 RootCA (根证书)并自签署证书(支持 IP 地址)

背景 某机房内部访问需要配置 HTTPS,网上找的一些证书教程都不是特别好,有些直接生成证书,没有根 CA 的证书导致信任不了 Ubuntu 机器,有些教程只有域名生成,没有 IP 生成,有些甚至报错。故发一个笔者在 Ubuntu 22.04 机器上测试正确可用的流程,这里使用 10.12.0.2