单元测试
如果你对自动化测试不感兴趣可以跳过本节。
通过编写单元测试,我们可以不经过用户界面来直接测试 PersonAppService.GetPeople 方法。
我们在.Tests项目中编写单元测试。首先我们先创建一个获取全部人员的单元测试:
public class PersonAppService_Tests : AppTestBase
{
private readonly IPersonAppService _personAppService;
public PersonAppService_Tests()
{
this._personAppService = Resolve<IPersonAppService>();
}
[Fact]
public void Should_Get_All_People_Without_Any_Filter()
{
//Act
var persons = this._personAppService.GetPeople(new GetPeopleInput());
//Assert
persons.Items.Count.ShouldBe(2);
}
}
我们的测试类继承与AppTestBase,AppTestBase类进行了系统的初始化,创建虚拟的内存数据库,在数据库中创建了初始化数据(前面的Seed文件)并模拟Admin身份登录了系统。所以,其实这是一个集成测试。
在测试类构造函数中,我们从依赖注入容器中获取了IPersonAppService ,它构造了PersonAppService 类和所有的依赖。然后我们就可以在测试中使用这个方法了。
因为使用的是XUnit,我们需要在每个测试方法前添加Fact属性。在这个测试方法里,我们调用了GetPeople方法,并检查它是否返回2个人,正如前面我们在Seed文件中添加的那样。
再来看AppTestBase基类
protected AppTestBase()
{
//Seed initial data for host
AbpSession.TenantId = null;
UsingDbContext(context =>
{
context.EntityChangeEventHelper = NullEntityChangeEventHelper.Instance;
context.EventBus = NullEventBus.Instance;
new InitialHostDbBuilder(context).Create();
new DefaultTenantBuilder(context).Create();
//Add
new InitialPeopleCreator(context).Create();
});
//Seed initial data for default tenant
var defaultTenantId = 1;
AbpSession.TenantId = defaultTenantId;
UsingDbContext(context =>
{
context.EntityChangeEventHelper = NullEntityChangeEventHelper.Instance;
context.EventBus = NullEventBus.Instance;
new TenantRoleAndUserBuilder(context, defaultTenantId).Create();
new TestDataBuilder(context, defaultTenantId).Create();
});
LoginAsDefaultTenantAdmin();
}
在构造函数中,进行了数据的初始化,所以需要增加InitialPeopleCreator方法的调用。
当我们在测试资源管理器中运行该测试后,会如下图所示:
如你所见,测试通过。现在,我们知道PersonAppService 在没有任何Filter的情况下能正常运行。下面,我们来添加一个新的单元测试,来使用Filter属性过滤。
[Fact]
public void Should_Get_People_With_Filter()
{
//Act
var persons = this._personAppService.GetPeople(
new GetPeopleInput
{
Filter = "Chow"
});
//Assert
persons.Items.Count.ShouldBe(1);
persons.Items[0].Name.ShouldBe("Alistair");
persons.Items[0].Surname.ShouldBe("Chow");
}
因为我们知道初始数据,所以检查返回结果很容易。这里,初始化测试数据非常重要,当我们改变了初始数据,即使我们的的服务是正确,测试也可能会失败。所以,单元测试最好是针对独立的初始数据来进行测试。我们检查传入的数据,看看是否有人的姓,名或邮箱地址里包含”Chow”。因此,如果我们添加新的Person到初始化数据,我们的测试仍然可以正常运行。
在单元测试里有很多技巧,这里只是最简单的例子。但ASP.NET Zero框架能通过使用基类和预生成测试代码,能很容易编写单元测试和集成测试。
通过浏览器控制台进行测试
现在,我们运行并登录这个应用,并打开Chorme 的开发者工具(或者在其他浏览器里的类似的工具)并编写下面的命令:
这个命令会执行Ajax调用PersonAppService的GetPeople方法。我们可以在Network标签下看这个请求:
正如我们所见,Ajax请求成功获取到人员信息。
所以,它通过什么机制运行的?我们怎么可以使用类似于Javascript的语法来调用C#类的方法?这是ABP框架提供的。见动态Web API 层了解更多。你可以随时使用控制台来调用应用服务来调试或查看返回Json的结构。
我们也可以查看请求的日志信息。打开AbpAuditLogs表就会看到下面的信息:
有很多其他的字段上图并没有显示出来。这里我们可以看到 ID = 2的用户调用了PersonAppService的GetPeople方法,参数,还有他的执行时间。