Debugging 为什么';在使用dart:io进行单元测试期间,进程是否退出?

Debugging 为什么';在使用dart:io进行单元测试期间,进程是否退出?,debugging,dart,Debugging,Dart,下面的代码在客户端发送的服务器上测试接收到的数据 导入'dart:async'; 导入“dart:convert”; 导入“dart:io”; 导入“包:unittest/unittest.dart”; main(){ 服务器插座; setUp(()=>ServerSocket.bind('localhost',9876)。然后((e)=>ss=e)); 拆卸(()=>ss.close()); 测试(‘测试1’,(){ 最后一行=新的完成符(); 听((s)=>s.map(UTF8.decode

下面的代码在客户端发送的服务器上测试接收到的数据

导入'dart:async';
导入“dart:convert”;
导入“dart:io”;
导入“包:unittest/unittest.dart”;
main(){
服务器插座;
setUp(()=>ServerSocket.bind('localhost',9876)。然后((e)=>ss=e));
拆卸(()=>ss.close());
测试(‘测试1’,(){
最后一行=新的完成符();
听((s)=>s.map(UTF8.decode)。听((s)=>line.complete(s));
插座连接(ss地址,ss端口)
。然后((s){
s、 写入(“测试”);
返回s.close();
})
.然后(())=>line.future)
。然后(expectAsync((s)=>expect(s,等于('test'));
});
}
此测试显示:

unittest-suite-wait-for-done
PASS: test 1

All 1 tests passed.
unittest-suite-success
然而,这个过程并没有停止

  • 为什么即使使用
    ss.close()
    s.close()
    ,进程仍在运行
  • 如何找到使流程保持活力的因素?是否提供了一些调试工具

  • 编辑:见下面Alex的答案。插座。排水管()FTW

    根据报告,服务器创建的套接字仍然可以写入。我已经更新了下面的代码来调用服务器和客户端套接字。在两个方向上关闭a

    导入'dart:async';
    导入“dart:convert”;
    导入“dart:io”;
    导入“包:unittest/unittest.dart”;
    main(){
    服务器插座;
    setUp(()=>ServerSocket.bind('localhost',9876)。然后((e)=>ss=e));
    拆卸(()=>ss.close());
    测试(‘测试1’,(){
    最后一行=新的完成符();
    听一听(s){
    s、 映射(UTF8.decode)。听((t){
    行。完成(t);
    s、 破坏();
    });
    });
    插座连接(ss地址,ss端口)
    。然后((s){
    s、 写入(“测试”);
    返回s.flush()。然后((){
    s、 破坏();
    回归线。未来;
    });
    })
    。然后(expectAsync((s)=>expect(s,等于('test'));
    });
    }
    
    根据
    drain()
    close()
    应优先选择,而不是
    destroy()

    以下是工作版本:

    导入'dart:async';
    导入“dart:convert”;
    导入“dart:io”;
    导入“包:unittest/unittest.dart”;
    main(){
    服务器插座;
    setUp(()=>ServerSocket.bind('localhost',9876)。然后((e)=>ss=e));
    拆卸(()=>ss.close());
    测试(‘测试1’,(){
    最后一行=新的完成符();
    ss.listen((s)=>UTF8.decodeStream(s)
    .然后((值)=>line.complete(值))
    .然后()=>s.close());
    插座连接(ss地址,ss端口)
    。然后((s){
    s、 写入(“测试”);
    返回Future.wait([s.drain(),s.close()]);
    })
    .然后(())=>line.future)
    。然后(expectAsync((s)=>expect(s,等于('test'));
    });
    }
    
    对此有一些评论:

    • 在服务器端,我使用了
      UTF8.decodesestream(s)。然后(…)
      而不是
      s.map(UTF8.decode)。侦听(…)
      ,因为值可以分为几个块。在这种情况下,插座会过早关闭
    • 在客户端,我使用了
      Future.wait([s.drain(),s.close()])
      而不是链接期货。如果我使用
      s.drain(),那么((=>s.close())
      进程会阻塞,因为服务器正在等待数据流的结束(由客户端的
      s.close()
      触发)关闭套接字,从而触发客户端的
      s.drain()
      完成
    支持调试的问题尚未解决,此类问题可能与调试此问题的工具类似。有关如何调试事件队列,请参见此处。谢谢Greg。
    close()
    只是关闭了写入流,这一点并不明显(的这种行为仅在:-/)中进行了描述。我也被它绊倒了好几次。也许有必要提出一个bug,要么需要改进文档,要么简化api。我还以为在服务器和客户端分别调用close()一次就足够了,但事实并非如此。如果能从熟悉实施细节的人那里得到更好的答案,那就太好了。我同意。我希望
    close()
    具有
    destroy()
    行为。从api的角度来看,我希望类似于
    close({bool writing:true,bool reading:true})
    。所以我不确定这是否可能。也许在邮件列表上发布,看看安德斯是否能对此有所启发。也许有一种更简单的方法可以做到这一点,但我遗漏了一些东西。我认为使用destroy()应该是最后的手段,关闭套接字的两端就足够了。如果两个destroy()调用都替换为close(),并且在s.write()之后添加了一个s.drain(),那么也可以删除s.flush。这是一个更好的解决方案,因为它正是连接终止和消失所需的功能:两端都必须关闭,两端都必须监听。