【问题标题】:What is the correct way to test this Task?测试此任务的正确方法是什么?
【发布时间】:2016-10-18 21:53:20
【问题描述】:

我有一个使用任务和异步/等待重复工作的方法。

    public static Task ToRepeatingWork(this Action work, int delayInMilliseconds)
    {
        Action action = async () =>
        {                
            while (true)
            {
                try
                {
                    work();
                }
                catch (MyException ex)
                {
                    // Do Nothing
                }
                await TaskEx.Delay(new TimeSpan(0, 0, 0, 0, delayInMilliseconds));
            }
        };
        return new Task(action, SomeCt, TaskCreationOptions.LongRunning);
    }

我已经写了一个对应的测试:

    [TestMethod, TestCategory("Unit")]
    public async Task Should_do_repeating_work_and_rethrow_exceptions()
    {
        Action work = () =>
        {
            throw new Exception("Some other exception.");
        };

        var task = work.ToRepeatingWork(1);
        task.Start();
        await task;
    }

我预计这个测试会失败,但它会通过(并使测试运行器崩溃)。

但是,如果在 ToRepeatingWork 方法中,我将操作从异步更改为正常操作并使用等待而不是等待,则测试会按预期运行。

TaskEx.Delay(new TimeSpan(0, 0, 0, 0, delayInMilliseconds)).Wait();

这里有什么问题?

【问题讨论】:

  • TaskEx? Ex?你是说2016年你还在使用异步preview
  • 你能做await work.ToRepeatingWork(1);,而不是显式启动它何时退出 While 循环,看起来永远不会
  • TaskEx,我们需要应用程序在 .Net 4.0 中运行。使用 TaskEx 以便延迟和运行可用。
  • 您的单元测试运行者了解异步测试吗?
  • @MrinalKamboj 真正的代码采用CancellationToken,它在while循环中使用。我不是必须在await它之前开始任务吗?

标签: c# unit-testing async-await task mstest


【解决方案1】:

你永远不应该使用任务构造函数。如果您有工作要放在线程池上,请使用Task.Run。这是一个问题,但不是导致崩溃的原因。

您还应该避免使用async void,因此请使用Func<Task> 而不是Action。这就是导致崩溃的原因。

public static Task ToRepeatingWork(this Action work, int delayInMilliseconds)
{
  Func<Task> action = async () =>
  {                
    while (true)
    {
      try
      {
        work();
      }
      catch (MyException ex)
      {
        // Do Nothing
      }
      await TaskEx.Delay(new TimeSpan(0, 0, 0, 0, delayInMilliseconds));
    }
  };
  return Task.Run(() => action());
}

[TestMethod, TestCategory("Unit")]
public async Task Should_do_repeating_work_and_rethrow_exceptions()
{
  Action work = () =>
  {
    throw new Exception("Some other exception.");
  };

  var task = work.ToRepeatingWork(1);
  await task;
}

【讨论】:

  • 您没有将传递给 Task.Run 的 lambda 标记为异步的原因吗?这与 Task.Run(async () =&gt; await action()) 有什么区别?感谢您的帮助
  • @SharePointNewbie: It's the same thing.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多