【发布时间】:2018-06-13 16:50:14
【问题描述】:
我目前正在尝试在使用 Microsoft Bot Framework 的应用程序中测试以下代码。
public async Task ResumeAfterCalculation_v2FormDialog(IDialogContext context, IAwaitable<Calculation_v2Form> result)
{
try
{
var extractedCalculationForm = await result;
//Removed additional code
}
catch (FormCanceledException ex)
{
var reply = "You have canceled the operation.";
await _chat.PostAsync(context, reply);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
finally
{
context.Done<object>(null);
}
}
当用户向机器人键入“退出”时,“等待结果”代码会引发 FormCanceledException,并且代码会退出表单。
在创建测试时,我实现了一个类来模拟 IAwaitable:
public class TaskAwaiterHelper<T> : IAwaiter<T>, IAwaitable<T>
{
public Task<T> Task { get; }
public TaskAwaiterHelper(T obj)
{
this.Task = System.Threading.Tasks.Task.FromResult(obj);
}
public TaskAwaiterHelper(Task<T> task)
{
this.Task = task;
}
public bool IsCompleted { get { return Task.IsCompleted; } }
public void OnCompleted(Action action)
{
SynchronizationContext context = SynchronizationContext.Current;
TaskScheduler scheduler = context == null ? TaskScheduler.Current
: TaskScheduler.FromCurrentSynchronizationContext();
Task.ContinueWith(ignored => action(), scheduler);
}
public T GetResult()
{
return Task.Result;
}
public IAwaiter<T> GetAwaiter()
{
return this;
}
}
然后我创建了以下测试:
[Fact]
public async Task ResumeAfterCalculation_v2FormDialog_WasCancelled_ThenCallsDone()
{
//Arrange
var chat = new Mock<IChatHelper>();
var calculationApi = new Mock<ICalculationApi>();
var dialogContextMock = new Mock<IDialogContext>();
var rootLuisDialog = new RootLuisDialog(chat.Object, calculationApi.Object);
var taskAwaiter = new TaskAwaiterHelper<Calculation_v2Form>(new Task<Calculation_v2Form>(() =>
{
throw new FormCanceledException("Error created for test test", null);
}));
taskAwaiter.Task.Start();
//Act
await rootLuisDialog.ResumeAfterCalculation_v2FormDialog(dialogContextMock.Object, taskAwaiter);
//Assert
chat.Verify(c => c.PostAsync(dialogContextMock.Object, "You have canceled the operation."), Times.Once());
dialogContextMock.Verify(t => t.Done<object>(null), Times.Once());
}
现在无论我尝试做什么,在 IAwaitable 中引发的异常都被包装在 AggregateException 中,因此我们总是以 catch (Exception ex) 而不是所需的 catch (FormCanceledException ex) 结束
有没有办法让任务抛出特定异常而不是 AggregateException(我的意思是应该有,因为机器人框架本身似乎能够做到这一点)。
【问题讨论】:
标签: c# unit-testing botframework