ASP.NET Core MVC / Razor Pages: 测试

你可以参考ASP.NET Core集成测试文档了解ASP.NET Core集成测试的详细内容. 本文档解释了ABP框架提供的附加测试基础设施.

应用程序启动模板

应用程序启动模板的.Web项目其中包含应用程序的UI视图/页面/组件, 并提供.Web.Tests项目来测试这些内容.

aspnetcore-web-tests-in-solution

测试Razor页面

假设你已经创建了一个名为Issues.cshtml的Razor页面, 包含以下内容;

Issues.cshtml.cs

  1. using System.Collections.Generic;
  2. using System.Threading.Tasks;
  3. using Microsoft.AspNetCore.Mvc.RazorPages;
  4. using MyProject.Issues;
  5. namespace MyProject.Web.Pages
  6. {
  7. public class IssuesModel : PageModel
  8. {
  9. public List<IssueDto> Issues { get; set; }
  10. private readonly IIssueAppService _issueAppService;
  11. public IssuesModel(IIssueAppService issueAppService)
  12. {
  13. _issueAppService = issueAppService;
  14. }
  15. public async Task OnGetAsync()
  16. {
  17. Issues = await _issueAppService.GetListAsync();
  18. }
  19. }
  20. }

Issues.cshtml

  1. @page
  2. @model MyProject.Web.Pages.IssuesModel
  3. <h2>Issue List</h2>
  4. <table id="IssueTable" class="table">
  5. <thead>
  6. <tr>
  7. <th>Issue</th>
  8. <th>Closed?</th>
  9. </tr>
  10. </thead>
  11. <tbody>
  12. @foreach (var issue in Model.Issues)
  13. {
  14. <tr>
  15. <td>@issue.Title</td>
  16. <td>
  17. @if (issue.IsClosed)
  18. {
  19. <span>Closed</span>
  20. }
  21. else
  22. {
  23. <span>Open</span>
  24. }
  25. </td>
  26. </tr>
  27. }
  28. </tbody>
  29. </table>

本页仅创建一个包含issue的表格:

issue-list

你可以在.Web.Tests项目中编写一个测试类如下所示:

  1. using System.Threading.Tasks;
  2. using HtmlAgilityPack;
  3. using Shouldly;
  4. using Xunit;
  5. namespace MyProject.Pages
  6. {
  7. public class Issues_Tests : MyProjectWebTestBase
  8. {
  9. [Fact]
  10. public async Task Should_Get_Table_Of_Issues()
  11. {
  12. // Act
  13. var response = await GetResponseAsStringAsync("/Issues");
  14. //Assert
  15. var htmlDocument = new HtmlDocument();
  16. htmlDocument.LoadHtml(response);
  17. var tableElement = htmlDocument.GetElementbyId("IssueTable");
  18. tableElement.ShouldNotBeNull();
  19. var trNodes = tableElement.SelectNodes("//tbody/tr");
  20. trNodes.Count.ShouldBeGreaterThan(0);
  21. }
  22. }
  23. }

GetResponseAsStringAsync是一个快捷方法, 它来自执行HTTP GET请求的基类, 检查生成的HTTP状态是否为200, 并将响应作为string返回.

你可以使用Client对象(类型为HttpClient)对服务器执行任何类型的请求, 并读取响应.GetResponseAsStringAsync只是一种快捷方法.

本例使用HtmlAgilityPack库来解析传入的HTML并测试它是否包含issue表格.

本例假设的数据库中存在一些初始issue. 请参阅测试文档种子数据部分, 了解如何设置种子数据, 以便可以假定数据库中有一些可用的初始数据.

控制器测试

测试控制器也不例外. 只需使用正确的URL向服务器执行请求, 获取响应并做出断言.

查看结果

如果控制器返回一个视图, 你可以使用类似的代码来测试返回的HTML. 参见上面的Razor页面示例.

对象结果

如果控制器返回对象结果, 则可以使用GetResponseAsObjectAsync方法.

假设你有一个如下定义的控制器:

  1. using System.Collections.Generic;
  2. using System.Threading.Tasks;
  3. using Microsoft.AspNetCore.Mvc;
  4. using MyProject.Issues;
  5. using Volo.Abp.AspNetCore.Mvc;
  6. namespace MyProject.Web.Controllers
  7. {
  8. [Route("api/issues")]
  9. public class IssueController : AbpController
  10. {
  11. private readonly IIssueAppService _issueAppService;
  12. public IssueController(IIssueAppService issueAppService)
  13. {
  14. _issueAppService = issueAppService;
  15. }
  16. [HttpGet]
  17. public async Task<List<IssueDto>> GetAsync()
  18. {
  19. return await _issueAppService.GetListAsync();
  20. }
  21. }
  22. }

你可以编写测试代码来调用API并获得结果:

  1. using System.Collections.Generic;
  2. using System.Threading.Tasks;
  3. using MyProject.Issues;
  4. using Shouldly;
  5. using Xunit;
  6. namespace MyProject.Pages
  7. {
  8. public class Issues_Tests : MyProjectWebTestBase
  9. {
  10. [Fact]
  11. public async Task Should_Get_Issues_From_Api()
  12. {
  13. var issues = await GetResponseAsObjectAsync<List<IssueDto>>("/api/issues");
  14. issues.ShouldNotBeNull();
  15. issues.Count.ShouldBeGreaterThan(0);
  16. }
  17. }
  18. }

测试JavaScript代码

ABP框架不提供任何基础设施来测试JavaScript代码. 你可以使用任何测试框架和工具来测试JavaScript代码.

测试基础设施

Volo.Abp.AspNetCore.TestBase 提供了集成到ABP框架和ASP.NET Core的测试基础设施.

Volo.Abp.AspNetCore.TestBase 已经安装在 .Web.Tests 项目中.

此包提供的AbpAspNetCoreIntegratedTestBase作为派生测试类的基类. 上面使用的MyProjectWebTestBase继承自AbpAspNetCoreIntegratedTestBase, 因此我们间接继承了AbpAspNetCoreIntegratedTestBase.

基本属性

AbpAspNetCoreIntegratedTestBase 提供了测试中使用的以下基本属性:

  • Server: 在测试中托管web应用程序的TestServer实例.
  • Client: 为执行对测试服务器的请求配置HttpClient实例.
  • ServiceProvider: 可以在你需要时处理服务提供服务.

基本方法

AbpAspNetCoreIntegratedTestBase 提供了以下方法, 如果需要自定义测试服务器, 可以重写这些方法:

  • ConfigureServices 仅为派生测试类注册/替换服务时可以重写使用.
  • CreateHostBuilder 可用于自定义生成 IHostBuilder.

另请参阅