项目

ASP.NET Core MVC / Razor Pages:测试指南

您可以参考ASP.NET Core集成测试文档了解ASP.NET Core集成测试的详细信息。本文档重点介绍ABP框架提供的额外测试基础设施。

应用程序启动模板

应用程序启动模板包含两个关键项目:

  • .Web项目:承载应用程序的UI视图/页面/组件
  • .Web.Tests项目:用于测试这些UI元素

解决方案中的ASP.NET Core Web测试项目

Razor Pages测试实战

假设您创建了一个名为Issues.cshtml的Razor Page,包含以下内容:

Issues.cshtml.cs

using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.RazorPages;
using MyProject.Issues;

namespace MyProject.Web.Pages
{
    public class IssuesModel : PageModel
    {
        public List<IssueDto> Issues { get; set; }

        private readonly IIssueAppService _issueAppService;

        public IssuesModel(IIssueAppService issueAppService)
        {
            _issueAppService = issueAppService;
        }

        public async Task OnGetAsync()
        {
            Issues = await _issueAppService.GetListAsync();
        }
    }
}

Issues.cshtml

@page
@model MyProject.Web.Pages.IssuesModel
<h2>问题列表</h2>
<table id="IssueTable" class="table">
    <thead>
        <tr>
            <th>问题</th>
            <th>是否关闭</th>
        </tr>
    </thead>
    <tbody>
        @foreach (var issue in Model.Issues)
        {
            <tr>
                <td>@issue.Title</td>
                <td>
                    @if (issue.IsClosed)
                    {
                        <span>已关闭</span>
                    }
                    else
                    {
                        <span>开放中</span>
                    }
                </td>
            </tr>
        }
    </tbody>
</table>

该页面会生成一个展示问题的表格:

问题列表

.Web.Tests项目中编写测试类,示例如下:

using System.Threading.Tasks;
using HtmlAgilityPack;
using Shouldly;
using Xunit;

namespace MyProject.Pages
{
    public class Issues_Tests : MyProjectWebTestBase
    {
        [Fact]
        public async Task Should_Get_Table_Of_Issues()
        {
            // 执行操作
            var response = await GetResponseAsStringAsync("/Issues");

            // 验证结果
            var htmlDocument = new HtmlDocument();
            htmlDocument.LoadHtml(response);

            var tableElement = htmlDocument.GetElementbyId("IssueTable");
            tableElement.ShouldNotBeNull();

            var trNodes = tableElement.SelectNodes("//tbody/tr");
            trNodes.Count.ShouldBeGreaterThan(0);
        }
    }
}

GetResponseAsStringAsync是基类提供的快捷方法,它会执行HTTP GET请求,检查HTTP状态码是否为200,并将响应内容作为string返回。

您也可以直接使用基类的Client对象(类型为HttpClient)向服务器发送任意请求并自行处理响应。GetResponseAsStringAsync仅为便捷方法。

此示例使用HtmlAgilityPack库解析返回的HTML内容,并验证是否包含问题表格。

本示例假设数据库中已预置部分问题数据。关于如何植入测试数据,请参阅测试文档数据种子章节,确保测试可以基于预设数据运行。

控制器测试指南

控制器测试方法类似:向服务器发送正确URL的请求,获取响应并进行断言验证。

视图结果测试

如果控制器返回视图,可采用与前述Razor Pages示例相似的代码测试返回的HTML内容。

对象结果测试

如果控制器返回对象结果,可使用基类的GetResponseAsObjectAsync方法。

假设您有以下控制器定义:

using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using MyProject.Issues;
using Volo.Abp.AspNetCore.Mvc;

namespace MyProject.Web.Controllers
{
    [Route("api/issues")]
    public class IssueController : AbpController
    {
        private readonly IIssueAppService _issueAppService;

        public IssueController(IIssueAppService issueAppService)
        {
            _issueAppService = issueAppService;
        }

        [HttpGet]
        public async Task<List<IssueDto>> GetAsync()
        {
            return await _issueAppService.GetListAsync();
        }
    }
}

编写测试代码调用API并获取结果:

using System.Collections.Generic;
using System.Threading.Tasks;
using MyProject.Issues;
using Shouldly;
using Xunit;

namespace MyProject.Pages
{
    public class Issues_Tests : MyProjectWebTestBase
    {
        [Fact]
        public async Task Should_Get_Issues_From_Api()
        {
            var issues = await GetResponseAsObjectAsync<List<IssueDto>>("/api/issues");
            
            issues.ShouldNotBeNull();
            issues.Count.ShouldBeGreaterThan(0);
        }
    }
}

JavaScript 代码测试

ABP框架未提供专门的JavaScript测试基础设施。您可以选择任何适用的测试框架和工具来测试JavaScript代码。

测试基础设施详解

Volo.Abp.AspNetCore.TestBase包提供了与ABP和ASP.NET Core深度集成的测试基础设施。

Volo.Abp.AspNetCore.TestBase包已预安装在.Web.Tests项目中。

该包提供AbpWebApplicationFactoryIntegratedTest作为测试类的核心基类,继承自ASP.NET Core提供的WebApplicationFactory类。

前文使用的MyProjectWebTestBase基类即继承自AbpWebApplicationFactoryIntegratedTest,因此我们间接继承了AbpWebApplicationFactoryIntegratedTest的全部功能。

扩展阅读

在本文档中