关于本教程
本教程基于版本3.1
在本教程系列中,您将构建一个名为Acme.BookStore
的基于ABP的Web应用程序。该应用程序用于管理书籍及其作者的列表。它是使用以下技术开发的:
- 实体框架核心作为ORM提供者。
- MVC/Razor页面作为UI框架。
本教程分为以下部分:
第4部分:集成测试(此部分)
下载源代码
MVC (Razor Pages) UI with EF Core
在解决方案中测试项目
本部分介绍服务器端测试。解决方案中有几个测试项目:
每个项目都用于测试相关项目。测试项目使用以下库进行测试:
-
Xunit作为主要测试框架。
-
Shoudly作为断言库。
-
NSubstitute作为模拟库。
测试项目被配置为使用内存中的SQLite作为数据库。创建一个单独的数据库实例并播种(使用数据种子系统),为每个测试准备一个新的数据库。
添加测试数据
如果您已按照第一部分中的说明创建了数据种子贡献者,则相同的数据将在您的测试中可用。因此,您可以跳过此部分。如果尚未创建种子贡献者,则可以使用BookStoreTestDataSeedContributor
来为要在以下测试中使用的相同数据注入种子。
测试BookAppService
添加一个新的测试类,在Acme.BookStore.Application.Tests
项目的Books
命名控件(文件夹)中命名为BookAppService_Tests
:
using System.Threading.Tasks;
using Shouldly;
using Volo.Abp.Application.Dtos;
using Xunit;
namespace Acme.BookStore.Books
{
public class BookAppService_Tests : BookStoreApplicationTestBase
{
private readonly IBookAppService _bookAppService;
public BookAppService_Tests()
{
_bookAppService = GetRequiredService<IBookAppService>();
}
[Fact]
public async Task Should_Get_List_Of_Books()
{
//Act
var result = await _bookAppService.GetListAsync(
new PagedAndSortedResultRequestDto()
);
//Assert
result.TotalCount.ShouldBeGreaterThan(0);
result.Items.ShouldContain(b => b.Name == "1984");
}
}
}
-
Should_Get_List_Of_Books
测试只是简单的使用BookAppService.GetListAsync
方法来获取和检查书籍列表。 -
我们可以安全地检查“1984”这本书的名称,因为我们知道这本书已经存在于数据库中,因为我们已经将其添加到种子数据中。
将新的测试方法添加到创建新有效书的BookAppService_Tests
类中:
[Fact]
public async Task Should_Create_A_Valid_Book()
{
//Act
var result = await _bookAppService.CreateAsync(
new CreateUpdateBookDto
{
Name = "New test book 42",
Price = 10,
PublishDate = System.DateTime.Now,
Type = BookType.ScienceFiction
}
);
//Assert
result.Id.ShouldNotBe(Guid.Empty);
result.Name.ShouldBe("New test book 42");
}
添加一个尝试创建无效书籍并失败的新测试:
[Fact]
public async Task Should_Not_Create_A_Book_Without_Name()
{
var exception = await Assert.ThrowsAsync<AbpValidationException>(async () =>
{
await _bookAppService.CreateAsync(
new CreateUpdateBookDto
{
Name = "",
Price = 10,
PublishDate = DateTime.Now,
Type = BookType.ScienceFiction
}
);
});
exception.ValidationErrors
.ShouldContain(err => err.MemberNames.Any(mem => mem == "Name"));
}
- 由于
Name
的值为空,因此ABP将抛出AbpValidationException
异常。
最终的测试类应如下所示:
using System;
using System.Linq;
using System.Threading.Tasks;
using Shouldly;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Validation;
using Xunit;
namespace Acme.BookStore.Books
{
public class BookAppService_Tests : BookStoreApplicationTestBase
{
private readonly IBookAppService _bookAppService;
public BookAppService_Tests()
{
_bookAppService = GetRequiredService<IBookAppService>();
}
[Fact]
public async Task Should_Get_List_Of_Books()
{
//Act
var result = await _bookAppService.GetListAsync(
new PagedAndSortedResultRequestDto()
);
//Assert
result.TotalCount.ShouldBeGreaterThan(0);
result.Items.ShouldContain(b => b.Name == "1984");
}
[Fact]
public async Task Should_Create_A_Valid_Book()
{
//Act
var result = await _bookAppService.CreateAsync(
new CreateUpdateBookDto
{
Name = "New test book 42",
Price = 10,
PublishDate = System.DateTime.Now,
Type = BookType.ScienceFiction
}
);
//Assert
result.Id.ShouldNotBe(Guid.Empty);
result.Name.ShouldBe("New test book 42");
}
[Fact]
public async Task Should_Not_Create_A_Book_Without_Name()
{
var exception = await Assert.ThrowsAsync<AbpValidationException>(async () =>
{
await _bookAppService.CreateAsync(
new CreateUpdateBookDto
{
Name = "",
Price = 10,
PublishDate = DateTime.Now,
Type = BookType.ScienceFiction
}
);
});
exception.ValidationErrors
.ShouldContain(err => err.MemberNames.Any(mem => mem == "Name"));
}
}
}
打开“测试资源管理器”窗口(如果看不到,请使用“测试”->“窗体”->“测试资源管理器”菜单),然后运行所有测试:
恭喜,绿色图标表示测试已成功通过!
下一部分
请参阅本教程的下一部分。