dotnet core单元测试与集成测试 xunit的使用
相关资源
xunit官网: https://xunit.net/
单元测试官方文档: https://docs.microsoft.com/zh-cn/dotnet/core/testing/unit-testing-with-dotnet-test
集成测试官方文档: https://docs.microsoft.com/zh-cn/aspnet/core/test/integration-tests?view=aspnetcore-3.1
前言
什么是单元测试?
使用自动测试是确保软件应用程序按作者期望执行操作的一种绝佳方式。 软件应用程序有多种类型的测试。 其中包括集成测试、Web 测试、负载测试和其他测试。 “单元测试”用于测试个人软件组件或方法 。 单元测试仅应测试开发人员控件内的代码。 它们不应测试基础结构问题。 基础结构问题包括数据库、文件系统和网络资源。
此外,请记住还可使用编写测试的最佳做法。 例如,测试驱动开发 (TDD) 是指先编写单元测试,再编写该单元测试要检查的代码。 TDD 就像先编写书籍大纲,再编写该书籍。 它旨在帮助开发人员编写更简单、更具可读性的高效代码。
编写单元测试时,尽量不要引入基础结构依赖项。 这些依赖项会降低测试速度,使测试更加脆弱,应将其保留供集成测试使用。 可以通过遵循 Explicit Dependencies Principle(显式依赖项原则)和使用 Dependency Injection(依赖项注入)避免应用程序中的这些依赖项。 还可以将单元测试保留在单独的项目中,与集成测试相分隔。 这可确保单元测试项目没有引用或依赖于基础结构包。
什么是集成测试
集成测试可在包含应用支持基础结构(如数据库、文件系统和网络)的级别上确保应用组件功能正常。 ASP.NET Core 通过将单元测试框架与测试 Web 主机和内存中测试服务器结合使用来支持集成测试.
与单元测试相比,集成测试可在更广泛的级别上评估应用的组件。 单元测试用于测试独立软件组件,如单独的类方法。 集成测试确认两个或更多应用组件一起工作以生成预期结果,可能包括完整处理请求所需的每个组件。
这些更广泛的测试用于测试应用的基础结构和整个框架,通常包括以下组件:
- 数据库
- 文件系统
- 网络设备
- 请求-响应管道
单元测试使用称为 fake 或 mock 对象 的制造组件,而不是基础结构组件。
与单元测试相比,集成测试:
- 使用应用在生产环境中使用的实际组件。
- 需要进行更多代码和数据处理。
- 需要更长时间来运行。
因此,将集成测试的使用限制为最重要的基础结构方案。 如果可以使用单元测试或集成测试来测试行为,请选择单元测试。
创建api
结构如图:
其中startup.cs内容为:
public class Startup
{
public Startup(IConfiguration configuration,IWebHostEnvironment env)
{
this.Configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddEnvironmentVariables()
.SetBasePath(env.ContentRootPath)
.Build();
//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.AddSingleton<IConfiguration>(this.Configuration);
services.AddControllers();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
- 配置文件注意事项
在待测试项目中的配置文件appsettings.json
并不会被测试主机所读取,因为我们在上面创建测试主机的时候没有调用方法WebHost.CreateDefaultBuilder
为了能够在单元测试中使用项目配置文件,项目中的Startup.cs
中需要将默认的注入改为手动创建
其目的就是手动读取配置文件,重新初始化IConfiguration
对象,并将Configuration
对象加入依赖注入容器中
valuesController内容为:
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
private IConfiguration configuration;
public ValuesController(IConfiguration configuration)
{
this.configuration = configuration;
}
[HttpGet("{id}")]
public ActionResult<int> Get(int id)
{
var result = id + this.configuration.GetValue<int>("max");
return result;
}
}
创建xunit
其中ValuesApiUnitTest.cs内容为:
public class ValuesApiUnitTest
{
private TestServer testServer;
private HttpClient httpClient;
public ValuesApiUnitTest()
{
testServer = new TestServer(new WebHostBuilder().UseStartup<testApi.Startup>());
httpClient = testServer.CreateClient();
}
[Fact]
public async void GetTest()
{
var data = await httpClient.GetAsync("/api/values/100");
var result = await data.Content.ReadAsStringAsync();
Assert.Equal("200", result);
}
}
我们在构造函数中,通过TestServer拿到一个HttpClient对象,用它来模拟Http请求。我们写了一个测试用例,完整演示了单元测试的Arrange、Act和Assert三个步骤。
运行测试
查看测试结果:
测试post方法
ValuesController增加接口:
ValuesApiUnitTest中添加测试方法:
运行测试结果:
运行测试并调试
断点打在webapi中
断点打在xunit测试中
至此集成测试就完成了.
下面简单再介绍一下单元测试:
单元测试
在webapi中新增测试对象util.cs中的静态方法
在ValuesApiUnitTest.cs中编写测试用例:
运行测试,显示成功.
相对来说,单元测试没有依赖项,执行更快,更容易测试
总结
单元测试和集成测试在项目开发中至关重要,现有测试用例,就引申出了TDD(测试驱动开发)开发模式.