首页 .Net 十一、Abp vNext 基础篇丨测试

十一、Abp vNext 基础篇丨测试

系列文章列表,点击展示/隐藏

系列教程一目录:知识点源码解析

系列教程二目录:Bcvp AbpVnext讲解

系列教程三目录:单个知识点讲解

系列教程四目录:分库分表(日志系统案例讲解)

本文梯子

    正文

    前言

    祝大家国庆快乐,本来想国庆之前更新完的,结果没写完,今天把剩下的代码补了一下总算ok了。

    本章节也是我们后端日常开发中最重要的一步就是测试,我们经常听到的单元测试、集成测试、UI测试、系统测试,还有就是最常见的(人肉测试),这些理论知识我记得老张有个视频讲了2篇,欢迎大家可以去群里骚扰老张,我找不到那个链接了。

    话不多说直接上车!

    最终结果

    理论速过

    ABP 框架的设计考虑了可测试性。有一些不同级别的自动化测试;

    • 单元测试:您通常测试单个类(或几个类一起)。这些测试会很快。但是,您通常需要处理服务依赖项的模拟。
    • 集成测试:您通常会测试服务,但这次您不会模拟基本的基础设施和服务,以查看它们是否可以正常协同工作。
    • UI 测试:您测试应用程序的 UI,就像用户与您的应用程序交互一样。###

    单元测试与集成测试

    与单元测试相比,集成测试有一些显着的优势;

    • 更容易编写,因为您不需要建立模拟和处理依赖项。
    • 测试代码与所有真实的服务和基础设施(包括数据库映射和查询)一起运行,因此它更接近于真实的应用程序测试。

    虽然它们有一些缺点;

    • 与单元测试相比,它们更慢,因为所有的基础设施都是为每个测试用例准备的。
    • 服务中的一个错误可能会导致多个测试用例被破坏,因此在某些情况下可能更难找到真正的问题。

    我们建议混合使用:在必要的地方编写单元或集成测试,并且您认为编写和维护它是有效的。

    Abp的默认已经帮我们生成了测试模板

    • Domain.Tests用于测试您的域层对象(如域服务和实体)。
    • Application.Tests用于测试您的应用程序层(如Application Services)。
    • EntityFrameworkCore.Tests用于测试您的自定义存储库实现或 EF Core 映射(如果您使用其他数据库提供程序,此项目将有所不同)。
    • TestBase 包含一些被其他项目共享/使用的类。
    注意:HttpApi.Client.ConsoleTestApp不是自动化测试应用程序。这是一个示例控制台应用程序,展示了如何从 .NET 控制台应用程序使用您的 HTTP API。
    

    测试模板

    单元测试

    简单来看一下如何完成一个单元测试,依Blog实体为例,实体是领域层的一部分,我们应该在Domain.Tests项目中对其进行测试。Blog_Tests在Domain.Tests项目中创建一个类(领域服务同理、)

    此测试遵循 AAA(安排-行为-断言)模式;

    • 安排部分创建一个Blog实体。
    • 行为部分执行我们要为此案例测试的方法。
    • 断言部分检查Blog属性是否与我们期望的相同。
        public >Blog_Tests
        {
            [Theory]
            [InlineData("aaa")]
            [InlineData("bbb")]
            public void SetName(string name)
            {
                var blog = new Blog(Guid.NewGuid(), "test blog", "test");
                blog.SetName(name);
                blog.Name.ShouldBe(name);
            }
    
            [Theory]
            [InlineData("aaa")]
            [InlineData("bbb")]
            public void SetShortName(string name)
            {
                var blog = new Blog(Guid.NewGuid(), "test blog", "test");
                blog.SetShortName(name);
                blog.ShortName.ShouldBe(name);
            }
        }
    

    集成测试

    ABP 提供了一个完整的基础设施来编写集成测试。所有 ABP 基础设施和服务都将在您的测试中执行。应用程序启动模板附带为您预先配置的必要基础设施,启动模板配置为对 EF Core使用内存中的 SQLite数据库(对于 MongoDB,它使用Mongo2Go库)。因此,所有配置和查询都是针对真实数据库执行的,您甚至可以测试数据库事务。

    种子数据

    针对空数据库编写测试是不切实际的。大多数情况下,需要在数据库中获取一些初始数据。

    Bcvp.Blog.Core.TestBase层的CoreTestDataSeedContributor.cs中创建种子数据,这样我们就可以使用这些数据来测试了。

        public >CoreTestData : ISingletonDependency
        {
            public Guid Blog1Id { get; } = Guid.NewGuid();
            public Guid Blog1Post1Id { get; } = Guid.NewGuid();
            public Guid Blog1Post2Id { get; } = Guid.NewGuid();
            public Guid Blog1Post1Comment1Id { get; } = Guid.NewGuid();
            public Guid Blog1Post1Comment2Id { get; } = Guid.NewGuid();
            public string Tag1Name { get; } = "Tag1Name";
            public string Tag2Name { get; } = "Tag2Name";
        }
     public >CoreTestDataSeedContributor : IDataSeedContributor, ITransientDependency
        {
    
            private readonly CoreTestData _testData;
            private readonly IBlogRepository _blogRepository;
            private readonly IPostRepository _postRepository;
            private readonly ICommentRepository _commentRepository;
            private readonly ITagRepository _tagRepository;
            private readonly ICurrentTenant _currentTenant;
    
            public CoreTestDataSeedContributor(
                CoreTestData testData,
                IBlogRepository blogRepository,
                IPostRepository postRepository,
                ICommentRepository commentRepository,
                ITagRepository tagRepository,
                ICurrentTenant currentTenant)
            {
                _testData = testData;
                _blogRepository = blogRepository;
                _postRepository = postRepository;
                _commentRepository = commentRepository;
                _tagRepository = tagRepository;
                _currentTenant = currentTenant;
            }
    
            public async Task SeedAsync(DataSeedContext context)
            {
                
                using (_currentTenant.Change(context?.TenantId))
                {
                    await SeedBlogsAsync();
                    await SeedPostsAsync();
                    await SeedCommentsAsync();
                    await SeedTagsAsync();
    
                }
            }
    
    
            private async Task SeedBlogsAsync()
            {
                await _blogRepository.InsertAsync(new BlogCore.Blogs.Blog(_testData.Blog1Id, "The First Blog", "blog-1"));
            }
    
            private async Task SeedPostsAsync()
            {
                await _postRepository.InsertAsync(new Post(_testData.Blog1Post1Id, _testData.Blog1Id, "title", "coverImage", "url"));
                await _postRepository.InsertAsync(new Post(_testData.Blog1Post2Id, _testData.Blog1Id, "title2", "coverImage2", "url2"));
            }
    
            public async Task SeedCommentsAsync()
            {
                await _commentRepository.InsertAsync(new Comment(_testData.Blog1Post1Comment1Id, _testData.Blog1Post1Id, null, "text"));
                await _commentRepository.InsertAsync(new Comment(_testData.Blog1Post1Comment2Id, _testData.Blog1Post1Id, _testData.Blog1Post1Comment1Id, "text"));
            }
    
            public async Task SeedTagsAsync()
            {
                await _tagRepository.InsertAsync(new Tag(Guid.NewGuid(), _testData.Blog1Id, _testData.Tag1Name, 10));
                await _tagRepository.InsertAsync(new Tag(Guid.NewGuid(), _testData.Blog1Id, _testData.Tag2Name));
            }
        }
    

    使用种子数据

    小插曲

    开头我说中间出了点问题,这里我说一下,首先是我有2个接口名字写错了,Resharper应该自动帮我加Async后缀,但是有2个接口没有很奇怪。

    另一个问题之前我们开发的时候在用户操作上我们调用的UserLookupService<IdentityUsers>,这个用法是错误的,UserLookupService是基于IUser的一个扩展操作类public abstract alt="IUser" loading="lazy">

    完结撒花

    最后撒花,整个基础篇系列到此应该就结束了,从框架介绍到功能开发到测试,我们全方位对ABP进行了一次使用教学,虽然很多知识点没有用到,但是整篇文章操作下来,入门肯定是ok了。

    后面我会开始对ABP独立的知识点进行讲解其中会涉及源码应用场景等多种案例,目前的安排是模块化->授权->eventbus->考虑中 如果你对那块知识点感兴趣可以联系我,大家一起边写边学。

    联系作者:加群:867095512 @MrChuJiu

    项目源码地址:https://github.com/BaseCoreVueProject/ABPvNext.Blog.Core

    特别声明:本站部分内容收集于互联网是出于更直观传递信息的目的。该内容版权归原作者所有,并不代表本站赞同其观点和对其真实性负责。如该内容涉及任何第三方合法权利,请及时与824310991@qq.com联系,我们会及时反馈并处理完毕。