目录

介绍

背景

使用代码

兴趣点


介绍

已显示在AutoFixture中使用的固定装置(fixture)对于测试自动化是一个非常有用的概念。固定装置(fixture)不仅对单元测试有用,而且该概念也可以在集成测试中重用。在本文中,将解释什么是固定装置(fixture),以及该概念如何用于单元测试和集成测试。固定装置(fixture)总是有一个共同点:它们为您管理测试的“安排”部分,这不仅对单元测试,而且对所有类型的测试都是有用的。

背景

您对.NET Core应用程序的TDD有一定的经验,这将非常有帮助,其中包括模拟,最好是此处使用的.NET Core 3.1。拥有固定装置(fixture)的经验也很有用,但不是必需的。本文中显示的示例基于xUnit,但是概念和技术也可以应用于其他单元测试框架。

使用代码

首先,我们看一下要测试的代码。这里是:

[Route("api/[controller]")]
[ApiController]
public class SearchEngineController : ControllerBase
{private readonly ISearchEngineService _searchEngineService;public SearchEngineController(ISearchEngineService searchEngineService){_searchEngineService = searchEngineService;}[HttpGet("{queryEntry}", Name = "GetNumberOfCharacters")]public async Task<ActionResult<int>> GetNumberOfCharacters(string queryEntry){var numberOfCharacters = await _searchEngineService.GetNumberOfCharactersFromSearchQuery(queryEntry);return Ok(numberOfCharacters);}
}

从上面的代码中可以清楚地看出,它只是一个控制器方法,它调用某些接口方法并返回带有OK状态码(200)的结果。这是该接口的实现。

public class SearchEngineService : ISearchEngineService
{private readonly HttpClient _httpClient;public SearchEngineService(HttpClient httpClient){_httpClient = httpClient;}public async Task<int> GetNumberOfCharactersFromSearchQuery(string toSearchFor){var result = await _httpClient.GetAsync($"/search?q={toSearchFor}");var content = await result.Content.ReadAsStringAsync();return content.Length;}
}

此代码也非常简单。Web请求完成,并返回结果的长度。

这是在Startup类中添加依赖项的方式:

public void ConfigureServices(IServiceCollection services)
{services.AddControllers();var googleLocation = Configuration["Google"];services.AddHttpClient<ISearchEngineService, SearchEngineService>(c =>c.BaseAddress = new Uri(googleLocation)).SetHandlerLifetime(TimeSpan.FromMinutes(5)).AddPolicyHandler(GetRetryPolicy());
}

现在清楚的是,我们需要能够模拟两个依赖关系:

  • 内部依赖项:这是ISearchEngineService的实例注入控制器。
  • 外部依赖项:这是设置为添加HttpClient内容基址的搜索引擎(url)。对于集成测试,我们需要模拟一下,因为我们对其是否给出相同的响应并保持在线状态没有任何影响。

内部依赖项的模拟通常是出于单元测试的目的,使用Moq可以如本文所述。外部依赖项的模拟通常是出于集成测试目的而进行的,如本文所述,使用WireMock ,此处提供的一些代码来自此。此处显示的所有代码在GitHub上也可用。

这是使用固定装置(fixture)进行单元测试的样子:

[Fact]
public async Task GetTest()
{// arrangevar fixture = new Fixture().Customize(new AutoMoqCustomization());var service = fixture.Freeze<Mock<ISearchEngineService>>();service.Setup(a => a.GetNumberOfCharactersFromSearchQuery(It.IsNotNull<string>())).ReturnsAsync(8);var controller = fixture.Build<SearchEngineController>().OmitAutoProperties().Create();// actvar response = await controller.GetNumberOfCharacters("Hoi");// assertAssert.Equal(8, ((OkObjectResult)response.Result).Value);service.Verify(s => s.GetNumberOfCharactersFromSearchQuery("Hoi"), Times.Once);
}

我们在这里看到的是以下内容:

  1. 第一步是创建固定装置。
  2. 之后, 调用Freeze方法(在Create方法之前)以指定内部依赖性,我们希望在测试结束时进行一些验证。
  3. 内部依赖关系需要与Setup方法一起设置。
  4. 在测试方法的assert部分中,我们验证对内部依赖项(service实例)的调用

如测试的实现,需要一个NuGet包:AutoFixture.AutoMoq。

从.NET Core的最新版本开始,集成测试变得更加容易。与单元测试的主要区别在于集成更加真实(因此配置性更差)。在Startup类和Program类都包括在内。使用实际的内部依赖关系来代替模拟/存根(stubs)。只有外部依赖项需要模拟,因为它们可以脱机,具有变化的行为或不稳定,所有这些都不应破坏测试。这是使用固定装置(fixture)进行集成测试的方法:

[Fact]
public async Task GetTest()
{// arrangeusing (var fixture = new Fixture<Startup>()){using (var mockServer = fixture.FreezeServer("Google")){SetupStableServer(mockServer, "Response");var controller = fixture.Create<SearchEngineController>();// actvar response = await controller.GetNumberOfCharacters("Hoi");// assertvar request = mockServer.LogEntries.Select(a => a.RequestMessage).Single();Assert.Contains("Hoi", request.RawQuery);Assert.Equal(8, ((OkObjectResult)response.Result).Value);}}
}private void SetupStableServer(FluentMockServer fluentMockServer, string response)
{fluentMockServer.Given(Request.Create().UsingGet()).RespondWith(Response.Create().WithBody(response, encoding: Encoding.UTF8).WithStatusCode(HttpStatusCode.OK));
}

我们在这里看到的是类似的:

  1. 第一步是使用Startup类创建固定装置(fixture),一旦Create方法被调用,它就初始化所有依赖项。
  2. 之后,调用FreezeServer方法(在该Create方法之前)以设置外部依赖关系,我们希望在测试结束时进行一些验证。
  3. 内部依赖性需要使用一种自写SetupStableServer方法来设置,该方法描述某个请求需要某个响应。这将在此处更详细地说明。
  4. 在测试方法的assert部分中,我们验证发送到外部依赖项(模拟服务)的Web请求

实现诸如测试,需要另一个NuGet包:ConnectingApps.IntegrationFixture。

从上面的代码可以清楚地看到,使用固定装置(fixture)进行集成测试的方式与使用固定装置(fixture)进行单元测试的方式基本相同。但是,除了安排和验证内部依赖项外,还需要使用外部依赖项来完成。他的建议听起来很明显,但是在不使用夹具的情况下进行集成测试时,需要大量的样板以作解释。

兴趣点

在研究固定装置(fixture),使用固定装置(fixture)并撰写本文时,对我来说清楚的是,固定装置(fixture)的概念可以以多种方式使用。AutoFixture在编写单元测试的安排部分时很有用,但其固定装置(fixture)也可用于其他类型测试的(安排部分)。它使我们作为开发人员不必编写大量样板代码。

集成测试:固定装置多于自动装置相关推荐

  1. 好代码是管出来的——.Net Core集成测试与数据驱动测试

    软件的单元测试关注是的软件最小可执行单元是否能够正常执行,但是软件是由一个个最小执行单元组成的集合体,单元与单元之间存在着种种依赖或联系,所以在软件开发时仅仅确保最小单元的正确往往是不够的,为了保证软 ...

  2. junit4 集成测试_使用JUnit规则进行干净的集成测试

    junit4 集成测试 JUnit Rules的优势,尤其是在进行集成测试时,几乎不能被高估. 在本文中,我们将阐明ExternalResource扩展的有用性. 在我们必须使用抽象外部资源的第三方库 ...

  3. 使用JUnit规则进行干净的集成测试

    JUnit Rules的优势,尤其是在进行集成测试时,几乎不能被高估. 在本文中,我们将阐明ExternalResource扩展的有用性. 在我们必须使用抽象外部资源的第三方库的情况下,这些简化了灯具 ...

  4. [渝粤题库]西北工业大学电力系统自动装置

    电力系统自动装置 一. 单选题 (共21题,共42分) 发电机调速系统的失灵区( ). (2分) A.越大越好 B.越小越好 C.要合适 同步发电机无功调节特性特性下倾,对应的调差系数( ). (2分 ...

  5. 如何使用postman测试流文件_干货|如何用Postman做集成测试

    友情提示:本文适合已经掌握Postman基本用法的读者,即对接口相关概念有一定了解.已经会使用Postman进行模拟请求等基本操作. 使用Postman进行接口测试,一个重要方面是:我们需要考虑与其他 ...

  6. 浅谈软件自动化集成测试的流程

    浅谈自动化集成测试 相信从事软件测试专业的同行很早就知道了自动化的测试技术,也许大家也很想知道具体的软件自动化具体的运行实施过程.本人学识尚欠,目前无法对综合的软件自动化的测试进行阐述,但是本人通过不 ...

  7. springboot+mybatis ,出现多于的参数导致查询数据缺少

    在springboot+mybatis 中,经常会有多于的字段遗留在xml文件中,这种情况正常人会以为会判断空和null状态,不影响sql语句,但是实际上会有影响, 因为在parameter中未定义, ...

  8. AMNO.6 给出一个不多于5位的整数,要求 1、求出它是几位数 2、分别输出每一位数字 3、按逆序输出各位数字,例如原数为321,应输出123 输入 一个不大于5位的数字

    题目描述 给出一个不多于5位的整数,要求 1.求出它是几位数 2.分别输出每一位数字 3.按逆序输出各位数字,例如原数为321,应输出123 输入 一个不大于5位的数字 输出 三行 第一行 位数 第二 ...

  9. 论新时代软件测试人员的工作之道(四)自动化测试之单元及集成测试

    在我们的工作中,为了提高测试效率或者做出测试团队的业绩来,都不得不做很多的自动化,当然这包括测试环境搭建,测试数据构造,测试执行,压力及安全测试等等,但是在各个阶段中,应该怎么样做好自动化满足我们的业 ...

最新文章

  1. 威胁预警|多个挖矿僵尸网络开始使用ThinkPHP v5漏洞 威胁升级
  2. python大学教程吕云翔课后题答案_软件工程实用教程吕云翔-课后答案.doc
  3. Linux C : 进程管理实验:创建进程、上下文切换
  4. 直播丨2020数据技术嘉年华·金融峰会暨数据库大咖讲坛(第4期)
  5. 平均要取多少个(0,1)中的随机数才能让和超过1
  6. equals()重写之后为什么要重写hashCode()方法
  7. confirm() 中写html,confirm用法 Confirm……that……
  8. 华为校招C++开发岗面试经验——软件开发工程师
  9. SpringMVC表单标签简介
  10. phpmail通过qq发邮箱失败_PHP下利用PHPMailer配合QQ邮箱下的域名邮箱发送邮件
  11. 单细胞分析:归一化和回归(八)
  12. 如何测试硬盘软件,如何进行硬盘测试?磁盘健康检测方法介绍
  13. 小想法 | 开源一个自己的Python小项目「Park at ease」停车场管理系统
  14. 计算机综合能力描述,计算机综合应用能力实训报告
  15. js打开服务器缓存文件夹路径,浅谈微信页面入口文件被缓存解决方案
  16. 浙大oj(basic level)1002
  17. Python实现用户输入国家名称,打印出所输入的国家名称和首都。
  18. agx 刷机+系统迁移至SD/m2+pytorch+Eigen3.3.7配置教程
  19. Oracle12C安装配置
  20. 【CV】第 8 章:语义分割和神经风格迁移

热门文章

  1. php 字符串中文截取,PHP 截取中文字符串(支持多种编码)
  2. java swing 列表框_Java开发笔记(一百三十一)Swing的列表框
  3. C语言口令,某一本地口令验证函数(c语言环境,x86_32指令集)包含如下关键代码:某用户的口令保存在字符数组origpassw...
  4. matlab控制算法C语言,PID算法Matlab仿真程序和C程序
  5. 如果你需要品质背景素材,看过来
  6. 中国风楼盘房地产海报PSD分层模板来袭,每张都诗情画意
  7. 准备一些万圣节的乐趣——UI设计素材模板
  8. 炫彩渐变流体元素PSD分层海报模板,耍酷就选它做背景!
  9. linux shell 无法ssh,linux – BASH和/或.BASHRC在SU或SSH登录后无法正常工作,除非运行“bash”命令...
  10. Qt实现桌面右下角放置窗体