.NET Core测试桩同步执行异步Expression<Action<T>>方法的方案
解决异步方法在BackgroundTasksServiceStub中的同步执行问题
你的测试桩当前只处理了同步方法的调用,当遇到async Task类型的异步方法时,直接编译执行Action<T>不会等待异步任务完成,导致任务在后台运行,进而引发异常或不符合预期的测试行为。
修改思路是:在桩服务中识别目标方法是否返回Task或Task<T>,如果是异步方法,就编译成返回Task的委托并同步等待其完成;如果是同步方法,保持原有逻辑不变。
修改后的代码如下:
public class BackgroundTasksServiceStub : IBackgroundTasksService { private readonly IServiceProvider _serviceProvider; public BackgroundTasksServiceStub(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } public void RunBackgroundTask<T>(Expression<Action<T>> methodCall) { var service = _serviceProvider.GetService<T>(); if (service == null) return; // 解析表达式获取目标方法信息 if (methodCall.Body is MethodCallExpression methodCallExpr) { var methodInfo = methodCallExpr.Method; var returnType = methodInfo.ReturnType; // 判断是否是异步方法(返回Task或Task<T>) if (returnType == typeof(Task) || (returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(Task<>))) { // 编译为Func<T, Task>并同步等待任务完成 var func = Expression.Lambda<Func<T, Task>>(methodCall.Body, methodCall.Parameters).Compile(); func(service).GetAwaiter().GetResult(); return; } } // 同步方法按原有逻辑执行 var method = methodCall.Compile(); method(service); } }
关键说明
- 解析传入的
Expression<Action<T>>,提取调用的方法信息 - 通过判断方法返回类型是否为
Task或泛型Task<T>,识别异步方法 - 对异步方法,将表达式重新编译为
Func<T, Task>委托,调用后使用GetAwaiter().GetResult()同步等待任务完成(避免用.Wait(),防止上下文死锁) - 同步方法保持原有执行逻辑,不影响原有测试场景
内容的提问来源于stack exchange,提问作者The Fabio
相关产品推荐
相关产品推荐

