《ASP.NET Core 与 RESTful API 开发实战》-- (第9章)-- 读书笔记(上)

第 9 章 测试和文档

9.1 测试

测试是软件生命周期中的一个非常重要的阶段,对于保证软件的可靠性具有极其重要的意义

常见的测试方法有很多,根据不同的维度,可以把测试方法分为不同的类别

从观察结构的透明性方式上,分为白盒测试、黑盒测试和灰盒测试

从测试执行方式上,分为手动测试和自动化测试

从测试所涉及的层次上,分为单元测试、集成测试和系统测试

单元测试由开发人员完成,主要用来测试程序中的类以及其中的方法是否能够正确运行

在添加单元测试方法时,应遵循 Arrange-Act-Access 模式,使测试方法的代码更加规范,该模式指明了每个测试方法由以下3部分组成:

  • Arrange:为测试进行准备操作,如设置测试数据、变量和环境等
  • Act:执行要测的方法,如调用要测试的函数和方法
  • Assert:断言测试结果,验证被测试方法的输出是否与预期的结果一致

我们使用 xUnit 测试框架,为项目命名为 Library.API.Testing

项目创建完成后,将默认的 UnitTest1.cs 删除,并添加一个新类,名为 AuthorController_UnitTests,该类主要包含针对 AuthorController 中方法的测试方法

由于 AuthorController 的构造函数中引用了多个其他依赖项,如 IRepositoryWrapper 和 IMapper 等,可以使用 Moq 库来模拟

namespace Library.API.Testing
{
    public class AuthorController_UnitTests
    {
        private AuthorController _authorController;
        private Mock<IDistributedCache> _mockDistributedCache;
        private Mock<ILogger<AuthorController>> _mockLogger;
        private Mock<IMapper> _mockMapper;
        private Mock<IRepositoryWrapper> _mockRepositoryWrapper;
        private Mock<IUrlHelper> _mockUrlHelper;

        public AuthorController_UnitTests()
        {
            _mockRepositoryWrapper = new Mock<IRepositoryWrapper>();
            _mockMapper = new Mock<IMapper>();
            _mockLogger = new Mock<ILogger<AuthorController>>();
            _mockDistributedCache = new Mock<IDistributedCache>();
            _mockUrlHelper = new Mock<IUrlHelper>();
            _authorController = new AuthorController(_mockMapper.Object,  
                _mockRepositoryWrapper.Object,
                _mockLogger.Object,
                _mockDistributedCache.Object);

            _authorController.ControllerContext = new ControllerContext
            {
                HttpContext = new DefaultHttpContext()
            };
        }
    }
}

在 AuthorController 中用到了 Response 属性,该属性可以控制 HTTP 响应,如在 GetAuthorsAsync 方法中使用它为响应添加了自定义消息头

Response.Headers.Add("X-Pagination", JsonConvert.SerializeObject(paginationMetedata));

已实例化的 AuthorController 的 Response 属性默认为空,通过设置 ControllerContext,使得 AuthorController 对象的 Request 和 Response 属性将不再为空

接下来对 GetAuthorsAsync 添加测试方法

[Fact]
public async Task Test_GetAuthorsAsync()
{
    // Arrange
    var author = new Author
    {
        Id = Guid.NewGuid(),
        Name = "Author Test 1",
        Email = "author1@xxx.com"
    };

    var authorDto = new AuthorDto
    {
        Id = author.Id,
        Name = author.Name,
        Email = author.Email,
    };

    var authorList = new List<Author> {author};
    var authorDtoList = new List<AuthorDto> {authorDto};

    var parameters = new AuthorResourceParameters();
    var authors = new PagedList<Author>(authorList, totalCount: authorList.Count,
        pageNumber: parameters.PageNumber, pageSize: parameters.PageSize);

    _mockRepositoryWrapper.Setup(m => m.Author.GetAllAsync(It.IsAny<AuthorResourceParameters>()))
        .Returns(Task.FromResult(authors));
    _mockMapper.Setup(m => m.Map<IEnumerable<AuthorDto>>(It.IsAny<IEnumerable<Author>>()))
        .Returns(authorDtoList);
    _mockUrlHelper.Setup(m => m.Link(It.IsAny<string>(), It.IsAny<object>())).Returns("demo url");
    _authorController.Url = _mockUrlHelper.Object;

    // Act
    var actionResult = await _authorController.GetAuthorsAsync(parameters);

    // Assert
    List<AuthorDto> resourceCollection = actionResult.Value;
    Assert.True(1==resourceCollection.Count);
    Assert.Equal(authorDto,resourceCollection.First());

    Assert.True(_authorController.Response.Headers.ContainsKey("X-Pagination"));
}

上面的测试方法遵循了 Arrange-Act-Assert 的模式

当数据准备好后,调用待测试的方法,并得到该方法的返回值,之后使用 Assert 类提供的静态方法来验证结果是否符合预期

知识共享许可协议

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

欢迎转载、使用、重新发布,但务必保留文章署名 郑子铭 (包含链接: http://www.cnblogs.com/MingsonZheng/ ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。

如有任何疑问,请与我联系 (MingsonZheng@outlook.com) 。

原文地址:https://www.cnblogs.com/MingsonZheng/p/13538886.html