ASP.NET Core 中做集成测试的三种方案
Posted dotNET跨平台
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ASP.NET Core 中做集成测试的三种方案相关的知识,希望对你有一定的参考价值。
学习·进步
老张的哲学
不定期更新的
日常
在平时的开发中,我们很少会关注到测试的问题,更别说集成测试了,除非是公司有硬性要求或者是自己的开源项目中,为了整体架构的完整性,需要用测试来做辅助点缀,而更多的也仅仅是单元测试(说的就是我自己????),最近在写书的时候才进一步考虑到这一点,如何在一个ASP.NET Core框架中,引入集成测试呢?
这里我结合这三年开源的经验,总结了一些心得,给大家分享一下,如果有更好的建议,欢迎在评论区进行留言哟。
PS:单元测试就不说了,比较简单,最多就是依赖注入和MOCK的问题,不会的话也可以留言。
方案一:万物皆可Mock
在软件测试当中,我们经常,甚至是到处都会用到mock来处理对象实例化的问题,在单元测试中,mock十分常见,毕竟是为了测试一个小模块,其他的就不需要考虑,直接mock就行了,如果在集成测试的时候,如何测试接口呢,比如BlogController如何使用?我在blog.core项目中,就是这么使用到的,示例代码如下:
Mock<IBlogArticleServices> mockBlogSev = new Mock<IBlogArticleServices>();
Mock<ILogger<BlogController>> mockLogger = new Mock<ILogger<BlogController>>();
BlogController blogController;
private IBlogArticleServices blogArticleServices;
DI_Test dI_Test = new DI_Test();
public BlogController_Should()
{
mockBlogSev.Setup(r => r.Query());
var container = dI_Test.DICollections();
blogArticleServices = container.Resolve<IBlogArticleServices>();
blogController = new BlogController(mockLogger.Object);
}
说句实话,这并非是集成测试,这种写法可能比较低端,通过mock配合new,创建了控制器,然后调用接口,看起来不是很高大上,而且集成测试本来就是要测试整体性,不能把所有的参数都mock吧。同时官方好像也说过,不要到处使用mock。
而且,这种方案,也要考虑如何使用依赖注入的问题!
所以这种方案做集成测试我给:
⭐⭐
方案二:实例化TestServer对象
这种是比较常见的,也是微软官方架构项目eShopOnContainers的推荐方案,简单来说,就是微软提供了一个TestSever的类,为我们提供一个类似WebHost的宿主服务器,只不过是测试服务器,那如何测试Controller控制器呢,示例代码如下:
public TestServer CreateServer()
{
var path = Assembly.GetAssembly(typeof(CatalogScenariosBase))
.Location;
var hostBuilder = new WebHostBuilder()
.UseContentRoot(Path.GetDirectoryName(path))
.ConfigureAppConfiguration(cb =>
{
cb.AddJsonFile("appsettings.json", optional: false)
.AddEnvironmentVariables();
})
.UseStartup<Startup>();
var testServer = new TestServer(hostBuilder);
testServer.Host
.MigrateDbContext<CatalogContext>((context, services) =>
{
var env = services.GetService<IWebHostEnvironment>();
var settings = services.GetService<IOptions<CatalogSettings>>();
var logger = services.GetService<ILogger<CatalogContextSeed>>();
new CatalogContextSeed()
.SeedAsync(context, env, settings, logger)
.Wait();
})
.MigrateDbContext<IntegrationEventLogContext>((_, __) => { });
return testServer;
}
可以看到,通过new TestServer()的方式,生成一个服务器,就可以发起请求了,核心的还是我们的WebHostBuilder。
至于如何调用就更简单了,直接对server发起HttpClient请求即可:
using (var server = CreateServer())
{
var response = await server.CreateClient()
.GetAsync(Get.ItemById(1));
response.EnsureSuccessStatusCode();
}
这种是很简单的,而且也不用考虑mock的问题,毕竟用的直接就是web项目的WebHost宿主机Builder来构建的。
但是有一个很致命的问题,我们在.NET5以后,使用Autofac做依赖注入的容器,而且ConfigureServices也是没有返回值的,这样在使用上面的TestServer,就会报错,提示找不到Autofac服务。
但是如果你查看eShopOnContainers的源码后,就知道他们还是将ConfigureServices做了返回值处理:
public IServiceProvider ConfigureServices(IServiceCollection servic
{
// 自定义服务扩展
services.AddAppInsight(Configuration)
// and so on...
.AddCustomMVC(Configuration);
// 使用Autofac依赖注入容器
var container = new ContainerBuilder();
container.Populate(services);
return new AutofacServiceProvider(container.Build());
}
如果你能接受这种依赖注入的方式的话,也是可以使用这种方案的,这是一个注意点,要知道。
所以这种方案做集成测试我给:
⭐⭐⭐⭐
方案三:使用.UseTestServer()
除了上面的这种方式,还有一种方式,也是官方提供的,比较类似,也是通过创建宿主机服务器的形式,不过是新的HostBuilder的ConfigureWebHostDefaults方式创建的,示例代码如下:
public static IHostBuilder GetTestHost()
{
return new HostBuilder()
//替换autofac作为DI容器
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder
.UseTestServer()
.UseStartup<Startup>();
})
.ConfigureAppConfiguration((host, builder) =>
{
builder.SetBasePath(Directory.GetCurrentDirectory());
builder.AddJsonFile("appsettings.json", optional: true);
builder.AddEnvironmentVariables();
});
}
既然上面说了我们不能单独处理自定义容器,我们就和之前一样,指定就好,设计思路和我们的WebApi中的Program.cs特别像,然后使用起来就更加简单了:
using var server = await ArticleScenariosBase.GetTestHost().StartAsync();
// Action 发起接口请求
var response = await server.GetTestClientWithToken()
.GetAsync("/api/blogs?page=1&pageSize=5");
// Assert 确保接口状态码是200
response.EnsureSuccessStatusCode();
这种方案不仅兼容了第二种方案的优点,而且对之前我们设计的Autofac依赖注入容器没有做任何的修改。
所以这种方案做集成测试我给:
⭐⭐⭐⭐⭐
编者按:Blog.Core开源三周年
【原料】
个人开源项目Blog.Core马上就已经开源三周年了,经过许许多多的小伙伴功能努力的结果,希望给ASP.NET Core在国内的推广,提供一个落地级别的案例。
【制法】
A、累计提交上千次Commit;
B、配合前、后、认证、鉴权一体化方案;
C、不完全统计,被60+公司使用中;
【调味】
1.希望更多的小伙伴参与并提交PR。
2.希望更多的公司和组织使用,提供宝贵生产意见。
3.希望可以得到组织的孵化,让项目更进一步,有意者可以联系我。
Tips: 九月新内容,敬请期待。
HAPPY EVEY DAY!
以上是关于ASP.NET Core 中做集成测试的三种方案的主要内容,如果未能解决你的问题,请参考以下文章
使用 .NET Framework 集成测试 ASP.NET Core - 找不到 deps.json