ASP.NET CORE 2.* 利用集成测试框架覆盖HttpClient相关代码
我的asp.net core 项目里面大部分功能都是去调用别人的API ,大量使用HttpClient,公司单元测试覆盖率要求95%以上,很难做到不mock HttpClient 达到这个指数。
以下方法是我自己总结的在单元测试里 mock httpClient 的方式,基本思路是利用集成测试框架,mock外部调用的API ,达到httpClient 代码的覆盖。
代码地址:https://github.com/Halo-Shaka/LearningAspNetCoreIntegrationTesting.git
举个例子,创建一个简单的asp.net core 项目,里面只有一个api , api/values, 是个get 方法,
get 方法内部是去调用外部API, 随便写个方法 向google 发一个信息。
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
private readonly IHttpClientFactory _httpClientFactory;
private readonly IOptions<AppSettings> _options;
public ValuesController(IHttpClientFactory httpClientFactory, IOptions<AppSettings> options)
{
_httpClientFactory = httpClientFactory;
_options = options;
}
// GET api/values
[HttpGet]
public async Task<ActionResult> Get()
{
var client = _httpClientFactory.CreateClient();
var url = _options.Value.Url;
var payload = new
{
From = "China"
};
var requestMessage = new HttpRequestMessage(HttpMethod.Post, url)
{
Content = new StringContent(JsonConvert.SerializeObject(payload), Encoding.UTF8, "application/json")
};
try
{
var response = await client.SendAsync(requestMessage);
var content = await response.Content.ReadAsStringAsync();
if (response.StatusCode == HttpStatusCode.OK)
{
return Ok(content);
}
return BadRequest();
}
catch (Exception e)
{
return StatusCode(502);
}
}
}
这里面有个需要注意的地方,使用注入的httpClient, 外部访问的地址需要是配置的
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
} public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddHttpClient();
} // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
} app.UseHttpsRedirection();
app.UseMvc();
}
}

到此为止,基本功能就写完了,现在来写测试代码
添加 XUnit单元测试项目,添加如下包
Microsoft.AspNetCore.App
Microsoft.AspNetCore.Mvc.Testing
Microsoft.NET.Test.Sdk
Moq
利用集成测试的虚拟站点,把我们需要调用的外部API 伪造出来,
[Route("gateway")]
public class MockGatewayController : ControllerBase
{
[HttpPost]
public ActionResult<string> Logon([FromBody]LogonRequest request)
{
if (request.From == "China")
{
var behavior = MockGatewayData.MockBehavior;
return behavior.LogonResult();
}
return string.Empty;
}
}
public class LogonRequest
{
public string From { get; set; }
}
public interface IGatewayMockBehavior
{
ActionResult<string> LogonResult();
}
public class MockGatewayData
{
public static IGatewayMockBehavior MockBehavior { get; set; }
}
MockGatewayData类的作用是 让客户端能够访问到服务端,并指定想要返回的结果
接着创建 GenericWebApplicationFactory,并把刚伪造的 controller 指定到虚拟站点里面,
public class GenericWebApplicationFactory : WebApplicationFactory<Startup>
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureServices(services =>
{
services.AddMvc().AddApplicationPart(typeof(MockGatewayController).Assembly).AddControllersAsServices();
});
}
}
最后写测试代码
public class ValuesControllerTest : IClassFixture<GenericWebApplicationFactory>
{
public ValuesControllerTest(GenericWebApplicationFactory factory, ITestOutputHelper output)
{
this.factory = factory;
this.output = output;
} protected GenericWebApplicationFactory factory;
protected ITestOutputHelper output; [Fact]
public void GetRequest_GatewayInaccessible_ShouldReturn502()
{
var client = factory.WithWebHostBuilder(p => p.ConfigureServices(services =>
{
services.PostConfigure<AppSettings>(options => { options.Url = "https://aaaaaaaa"; });
})).CreateClient();
var response = client.SendAsync(new HttpRequestMessage(HttpMethod.Get, "api/values")).Result;
Assert.Equal(HttpStatusCode.BadGateway, response.StatusCode);
} [Fact]
public void GetRequest_GatewayOnFailed_ShouldReturn400()
{
var behavior = new Mock<IGatewayMockBehavior>();
behavior.Setup(p => p.LogonResult()).Returns(new BadRequestResult());
MockGatewayData.MockBehavior = behavior.Object; var client = CreateHttpClient();
var response = client.SendAsync(new HttpRequestMessage(HttpMethod.Get, "api/values")).Result;
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
} [Fact]
public void GetRequest_GatewayOnSuccess_ShouldReturn200()
{
var behavior = new Mock<IGatewayMockBehavior>();
behavior.Setup(p => p.LogonResult()).Returns(new ActionResult<string>("success"));
MockGatewayData.MockBehavior = behavior.Object; var client = CreateHttpClient();
var response = client.SendAsync(new HttpRequestMessage(HttpMethod.Get, "api/values")).Result;
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
} private HttpClient CreateHttpClient()
{
var client = factory.WithWebHostBuilder(p => p.ConfigureServices(services =>
{
services.PostConfigure<AppSettings>(options => { options.Url = "http://localhost/gateway"; }); services.AddSingleton(typeof(IHttpClientFactory), new MockHttpClientFactory
{
InjectHttpClient = factory.CreateClient
});
})).CreateClient(); return client;
}
}
最后看下覆盖率,整个controller 里面httpClient 全都被覆盖了

代码地址:
https://github.com/Halo-Shaka/LearningAspNetCoreIntegrationTesting.git
ASP.NET CORE 2.* 利用集成测试框架覆盖HttpClient相关代码的更多相关文章
- ASP.NET Core的身份认证框架IdentityServer4--入门
ASP.NET Core的身份认证框架IdentityServer4--入门 2018年08月11日 10:09:00 qq_42606051 阅读数 4002 https://blog.csdn ...
- Blazor——Asp.net core的新前端框架
原文:Blazor--Asp.net core的新前端框架 Blazor是微软在Asp.net core 3.0中推出的一个前端MVVM模型,它可以利用Razor页面引擎和C#作为脚本语言来构建WEB ...
- 基于Asp.Net Core,利用ZXing来生成二维码的一般流程
本文主要介绍如何在.net环境下,基于Asp.Net Core,利用ZXing来生成二维码的一般操作.对二维码工作原理了解,详情见:https://blog.csdn.net/weixin_36191 ...
- ASP.NET Core开发-使用Nancy框架
Nancy简介 Nancy是一个轻量级的独立的框架,下面是官网的一些介绍: Nancy 是一个轻量级用于构建基于 HTTP 的 Web 服务,基于 .NET 和 Mono 平台,框架的目标是保持尽可能 ...
- 使用Angular 4、Bootstrap 4、TypeScript和ASP.NET Core开发的Apworks框架案例应用:Task List
最近我为我自己的应用开发框架Apworks设计了一套案例应用程序,并以Apache 2.0开源,开源地址是:https://github.com/daxnet/apworks-examples,目的是 ...
- ASP.NET Core Web API 集成测试中使用 Bearer Token
在 ASP.NET Core Web API 集成测试一文中, 我介绍了ASP.NET Core Web API的集成测试. 在那里我使用了测试专用的Startup类, 里面的配置和开发时有一些区别, ...
- asp.net core 集成 log4net 日志框架
asp.net core 集成 log4net 日志框架 Intro 在 asp.net core 中有些日志我们可能想输出到数据库或文件或elasticsearch等,如果不自己去实现一个 Logg ...
- asp.net core 系列 8 Razor框架路由(下)
三.页面路由操作约定 接着上篇讲asp.net core 系列 7 Razor框架路由.在上篇继续第三节 "页面路由操作约定" 的最后一小节 AddPageRoute . 3.3. ...
- asp.net core 系列 5 MVC框架路由(上)
一. 概述 介绍asp.net core路由时,我初步想了下,分几篇来说明. 路由的知识点很多,参考了官方文档提取出一些重要的知识点来说. 在ASP.NET Core中是使用路由中间件来匹配传 ...
随机推荐
- Acrobat pro Dc 2018破解版|Adobe Acrobat pro Dc 2018中文破解版下载(附序列号/免破解)
Acrobat pro Dc 2018破解版是由Adobe公司开发的一款PDF编辑软件,它可以以PDF格式制作和保存用户的文档,以此方便浏览和打印,或使用更高级的功能,且PDF格式的文档可如实地保留原 ...
- k8s学习 - 概念 - Pod
k8s学习 - 概念 - Pod 这篇继续看概念,主要是 Pod 这个概念,这个概念非常重要,是 k8s 集群的最小单位. 怎么才算是理解好 pod 了呢,基本上把 pod 的所有 describe ...
- 【最小生成树之Prim算法】-C++
[最小生成树之Kruskal算法] 没有看过的可以先看↑,会更简单. [模板]最小生成树 这一篇博客主要是介绍另外一种算法:Prim算法. prim算法就好像是一棵"生成树"在慢慢 ...
- redis集群(单机6节点实现)
Redis集群搭建与简单使用 1.介绍安装环境与版本: 1)Redis使用的是Redis-3.2.8版本. 2)用一台虚拟机模拟6个节点,三个master节点,三个slave节点.虚拟机使用CentO ...
- Ambassador,云原生应用的“门神”
目前,行业内基于云原生思想的开源项目,重点在于管理.控制微服务以及微服务架构下服务之间的通信问题.它们有效的解决了“服务异构化”.“动态化”.“多协议”场景所带来的east/west流量的管控问题,而 ...
- TestNG中@Factory的用法一:简单的数据驱动
为什么要使用@Factory注解呢,先来看下面这个例子 被测试类Person package ngtest; import org.testng.annotations.Parameters; imp ...
- TestNG中group的用法
TestNG中的组可以从多个类中筛选组属性相同的方法执行. 比如有两个类A和B,A中有1个方法a属于组1,B中有1个方法b也属于组1,那么我们可以通过配置TestNG文件实现把这两个类中都属于1组的方 ...
- netty使用EmbeddedChannel对channel的出入站进行单元测试
一种特殊的Channel实现----EmbeddedChannel,它是Netty专门为改进针对ChannelHandler的单元测试而提供的. 名称 职责 writeInbound 将入站消息写到E ...
- Kotlin学习快速入门(5)——空安全
介绍 kotlin中,对象可分为两种类型,可为空的对象和不可为空对象 默认为不可为空对象,代码检测如果发现不可为空对象赋予了null,则会标红报错. 可为空的对象,如果调用了方法,代码检测也会标红报错 ...
- ansible批量管理服务 上
1 ansible简介 1.1 ansible批量管理服务概述 (1)是基于python语言开发的自动化软件工具(2)是基于SSH远程管理服务实现远程主机批量管理(3)并行管理,部署简单,应用也简单方 ...