ASP.NET Core MVC / Razor Pages 教程 - 第三章

关于本教程

这是ASP.NET CoreMVC / Razor Pages系列教程的第二章. 共有三章:

你也可以观看由ABP社区成员为本教程录制的视频课程.

解决方案中的测试项目

解决方案中有多个测试项目:

bookstore-test-projects-v2

每个项目用于测试相关的应用程序项目.测试项目使用以下库进行测试:

添加测试数据

启动模板包含Acme.BookStore.TestBase项目中的BookStoreTestDataSeedContributor类,它创建一些数据来运行测试. 更改BookStoreTestDataSeedContributor类如下所示:

  1. using System;
  2. using System.Threading.Tasks;
  3. using Volo.Abp.Data;
  4. using Volo.Abp.DependencyInjection;
  5. using Volo.Abp.Domain.Repositories;
  6. using Volo.Abp.Guids;
  7. namespace Acme.BookStore
  8. {
  9. public class BookStoreTestDataSeedContributor
  10. : IDataSeedContributor, ITransientDependency
  11. {
  12. private readonly IRepository<Book, Guid> _bookRepository;
  13. private readonly IGuidGenerator _guidGenerator;
  14. public BookStoreTestDataSeedContributor(
  15. IRepository<Book, Guid> bookRepository,
  16. IGuidGenerator guidGenerator)
  17. {
  18. _bookRepository = bookRepository;
  19. _guidGenerator = guidGenerator;
  20. }
  21. public async Task SeedAsync(DataSeedContext context)
  22. {
  23. await _bookRepository.InsertAsync(
  24. new Book(id: _guidGenerator.Create(),
  25. name: "Test book 1",
  26. type: BookType.Fantastic,
  27. publishDate: new DateTime(2015, 05, 24),
  28. price: 21
  29. )
  30. );
  31. await _bookRepository.InsertAsync(
  32. new Book(id: _guidGenerator.Create(),
  33. name: "Test book 2",
  34. type: BookType.Science,
  35. publishDate: new DateTime(2014, 02, 11),
  36. price: 15
  37. )
  38. );
  39. }
  40. }
  41. }
  • 注入IRepository<Book,Guid>并在SeedAsync中使用它来创建两个书实体作为测试数据.
  • 使用IGuidGenerator服务创建GUID. 虽然Guid.NewGuid()非常适合测试,但IGuidGenerator在使用真实数据库时还有其他特别重要的功能(参见Guid生成文档了解更多信息).

测试 BookAppService

Acme.BookStore.Application.Tests 项目中创建一个名叫 BookAppService_Tests 的测试类:

  1. using System;
  2. using System.Linq;
  3. using System.Threading.Tasks;
  4. using Xunit;
  5. using Shouldly;
  6. using Volo.Abp.Application.Dtos;
  7. using Volo.Abp.Validation;
  8. using Microsoft.EntityFrameworkCore.Internal;
  9. namespace Acme.BookStore
  10. {
  11. public class BookAppService_Tests : BookStoreApplicationTestBase
  12. {
  13. private readonly IBookAppService _bookAppService;
  14. public BookAppService_Tests()
  15. {
  16. _bookAppService = GetRequiredService<IBookAppService>();
  17. }
  18. [Fact]
  19. public async Task Should_Get_List_Of_Books()
  20. {
  21. //Act
  22. var result = await _bookAppService.GetListAsync(
  23. new PagedAndSortedResultRequestDto()
  24. );
  25. //Assert
  26. result.TotalCount.ShouldBeGreaterThan(0);
  27. result.Items.ShouldContain(b => b.Name == "Test book 1");
  28. }
  29. }
  30. }
  • 测试方法 Should_Get_List_Of_Books 直接使用 BookAppService.GetListAsync 方法来获取用户列表,并执行检查.

新增测试方法,用以测试创建一个合法book实体的场景:

  1. [Fact]
  2. public async Task Should_Create_A_Valid_Book()
  3. {
  4. //Act
  5. var result = await _bookAppService.CreateAsync(
  6. new CreateUpdateBookDto
  7. {
  8. Name = "New test book 42",
  9. Price = 10,
  10. PublishDate = DateTime.Now,
  11. Type = BookType.ScienceFiction
  12. }
  13. );
  14. //Assert
  15. result.Id.ShouldNotBe(Guid.Empty);
  16. result.Name.ShouldBe("New test book 42");
  17. }

新增测试方法,用以测试创建一个非法book实体失败的场景:

  1. [Fact]
  2. public async Task Should_Not_Create_A_Book_Without_Name()
  3. {
  4. var exception = await Assert.ThrowsAsync<Volo.Abp.Validation.AbpValidationException>(async () =>
  5. {
  6. await _bookAppService.CreateAsync(
  7. new CreateUpdateBookDto
  8. {
  9. Name = "",
  10. Price = 10,
  11. PublishDate = DateTime.Now,
  12. Type = BookType.ScienceFiction
  13. }
  14. );
  15. });
  16. exception.ValidationErrors
  17. .ShouldContain(err => err.MemberNames.Any(mem => mem == "Name"));
  18. }
  • 由于 Name 是空值, ABP 抛出一个 AbpValidationException 异常.

打开测试资源管理器(测试 -> Windows -> 测试资源管理器)并执行所有测试:

bookstore-appservice-tests

恭喜, 绿色图标表示测试已成功通过!