• 单元测试过多,导致The configured user limit (128) on the number of inotify instances has been reached.


    最近在一个asp.net core web项目中使用TDD的方式开发,结果单元测试超过128个之后,在CI中报错了:“The configured user limit (128) on the number of inotify instances has been reached.” 在本地却是正常的,如此诡异的事,必定要搞清楚。

    于是,从报错信息着手,一番Google无果之后,不得不冷静思考,报错的原因在哪里?通过异常信息定位到了是因为在测试中,每个测试都要开启一个TestServer,相当于运行一个站点,在站点Setup的时候,需要监听配置文件,在unix系统中是通过一个inotify的东西实现监听的,因此当监听那个配置文件的次数达到系统上限(CI服务器是128)就会抛出一个IO异常,而在本地却没有达到上限,因此是正常的。

    既然问题的原因找到了,那么解决问题的思路也就明确了。

    方案一:把CI服务器的限制调高

    方案二:减少集成测试中开启TestServer的次数

    对比这两种方案,第二种是最优解。

    一般在跨平台的core中,我们大多使用xunit框架进行测试,在xunit官方文档中,我发现有一节“Shared Context between Tests”,在各个测试中共享一个上下文,大家对上下文的概念应该不陌生,“It is common for unit test classes to share setup and cleanup code (often called "test context"). ”这里是指单元测试中需要共享的启动和清除代码,在我的项目中就是每个测试都需要开启的TestServer(运行asp.net core web站点服务),只要把TestServer放在上下文中就可以在单元测试中共享,不需要每个测试开启一次,那么就会大大减少TestServer的实例个数。

    稍微注意一点:在xunit框架中,单元测试默认是Test Collections级别的并发测试,默认一个类算一个Test Collections,那么类与类之间是并发的,而一个类中的所有的单元测试是串行的。当然所有的默认值都能自定义,详见:https://xunit.github.io/docs/running-tests-in-parallel.html

    实现我们的解决方案,其实很简单,就是使用xunit中的IClassFixture<>,下面引用一个官方文档中的例子,

    public class DatabaseFixture : IDisposable
    {
        public DatabaseFixture()
        {
            Db = new SqlConnection("MyConnectionString");
    
            // ... initialize data in the test database ...
        }
    
        public void Dispose()
        {
            // ... clean up test data from the database ...
        }
    
        public SqlConnection Db { get; private set; }
    }
    
    public class MyDatabaseTests : IClassFixture<DatabaseFixture>
    {
        DatabaseFixture fixture;
    
        public MyDatabaseTests(DatabaseFixture fixture)
        {
            this.fixture = fixture;
        }
    
        // ... write tests, using fixture.Db to get access to the SQL Server ...
    }
    

    MyDatabaseTests中的所有单元测试都会共享一个DatabaseFixture实例。

    然而,在我的项目中,使用了ABP框架,它封装的AbpAspNetCoreIntegratedTestBase<>并不能直接用IClassFixture<>,因此只能把ABP的源码签下来,自己修改一下,然后打包成Nuget包,发布到自己的源中。最后,顺便给ABP提交一个PullRequest

  • 相关阅读:
    c# webapi无法获取Session值问题解决
    深入理解java虚拟机之自动内存管理机制笔记
    数据结构总结1
    疯人院之语言、编码、计算机

    集线器/交换机
    什么是DOM?DOM和JavaScript的关系 [web开发]
    JSON轻量级的数据交换格式
    天问宇宙学第一课
    C++基础知识
  • 原文地址:https://www.cnblogs.com/kexxxfeng/p/7625205.html
Copyright © 2020-2023  润新知