在集成测试中验证测试结果时需要用到,请问如何用 C# 实现简单的进程内通信(In-Process Communication)?
候选解决方法:
在集成测试场景,不管 Anonymous Pipes
还是 Named Pipes
都不可行,因为 TestServer 与测试用例的执行在同一线程,会造成 server 与 client 互相等待的僵局。
(后来发现 TestServer 与测试用例不在同一个线程)
比如下面的代码会卡在 server 端 WaitForConnectionAsync
的地方
using var pipeServer = new NamedPipeServerStream(NamedPipeName, PipeDirection.Out);
await pipeServer.WaitForConnectionAsync();
await using var sw = new StreamWriter(pipeServer);
sw.AutoFlush = true;
await sw.WriteLineAsync(notification.Message);
测试用例中 client 端永远没有机会执行
await using var pipeClient = new NamedPipeClientStream(".", NamedPipeName, PipeDirection.In);
await pipeClient.ConnectAsync();
using var sr = new StreamReader(pipeClient);
string line;
while ((line = await sr.ReadLineAsync()) != null)
{
Debug.WriteLine("Received: " + line);
}
最终选用 Serilog.Sinks.InMemory 解决了问题
安装 nuget 包
dotnet add package Serilog.Sinks.InMemory
dotnet add package Serilog.Sinks.InMemory.Assertions
web 项目中记录日志
_logger.LogInformation(LogTemplates.HandledIntegratonEvent, notification);
日志消息模板
public const string HandledIntegratonEvent = "Handled integration event {@event}.";
集成测试中断言
InMemorySink.Instance
.Should()
.HaveMessage(LogTemplates.HandledIntegratonEvent)
.Appearing().Once()
.WithProperty("event")
.HavingADestructuredObject()
.WithProperty("Id")
.WithValue(@event.Id);
AnonymousPipeServerStream.WaitForPipeDrain() 方法不支持 linux
– dudu 1年前如果是同一个线程,可以通过
– dudu 1年前[ThreadStatic]
字段共享变量值,可惜不是How to maintain Thread context across async await model in C#? https://stackoverflow.com/q/23555255/5989202
– dudu 1年前