Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 如何在异步方法中测试异常_.net_Async Ctp_Visual Studio 2012 - Fatal编程技术网

.net 如何在异步方法中测试异常

.net 如何在异步方法中测试异常,.net,async-ctp,visual-studio-2012,.net,Async Ctp,Visual Studio 2012,我正在使用VisualStudio11测试版 鉴于此代码: namespace KC.DataAccess.Global { /// <summary>Global methods for SQL access</summary> public static class SQL { public async static void ExecuteNonQuery(string ConnStr, string Query)

我正在使用VisualStudio11测试版

鉴于此代码:

namespace KC.DataAccess.Global
{
    /// <summary>Global methods for SQL access</summary>
    public static class SQL
    {    
        public async static void ExecuteNonQuery(string ConnStr, string Query)
        {
            if (string.IsNullOrEmpty(ConnStr)) throw new ArgumentNullException("ConnStr");
            if (string.IsNullOrEmpty(Query)) throw new ArgumentNullException("Query");
            SqlConnection conn = new SqlConnection(ConnStr);
            SqlCommand cmd = PrepSqlConnection(ref conn, Query);
            Exception exc = null;
            for (int i = 0; i < 3; i++)
                try { await Task.Run(() => cmd.ExecuteNonQuery()); break; }
                catch (Exception ex) { Thread.Sleep(50); exc = ex; }
            if (exc != null) throw new ApplicationException("Command failed after maximum attempts", exc);
            conn.Close();
            conn.Dispose();
         }
    } 
} 
在本例中,ExecuteOnQuery的验证部分显然抛出了一个异常,我在调试它时看到它抛出

我已将测试方法更改为异步,并将语法更改为wait Task.Run=>Target.ExecuteNonQuery,但没有任何效果

问题:

ExecuteOnQuery是否正在引发异常? 为什么ExecuteOnQueryFail1没有看到异常? 在不放弃方法的异步性质的情况下,如何修改测试方法或方法本身,以正确处理异常并通过测试用例? 由于您的方法返回void,因此无法将异常传播到调用代码。如果将返回类型更改为Task,现在可以观察异常,但必须显式执行

我认为修改调用代码的最好方法就是调用。如果任务中的代码引发异常,Wait将引发包含原始异常的AggregateException。

由于方法返回void,因此异常无法传播到调用代码。如果将返回类型更改为Task,现在可以观察异常,但必须显式执行


我认为修改调用代码的最好方法就是调用。如果任务中的代码引发异常,Wait将引发包含原始异常的AggregateException。

VS11 Beta对返回任务的测试方法具有一流的支持

因此,如果您将签名更改为:

public async static Task ExecuteNonQuery(string ConnStr, string Query)
然后您可以对其进行如下测试:

using Target = KC.DataAccess.Global.SQL;
[TestMethod]
[TestCategory("Unit")]
[ExpectedException(typeof(ArgumentNullException))]
public async Task ExecuteNonQueryFail1()
{
  await Target.ExecuteNonQuery(null, "select 1");
}
我自己还没有机会尝试这种新的支持,但我已经读到这应该是可行的

注意:除非必须返回void(例如,对于事件处理程序),否则应该在异步方法中返回Task。任务是可等待的,因此代码更易于重用。我把这件事写进去

如果出于某种原因确实需要测试异步void方法,则需要提供自己的SynchronizationContext来捕获任何异常。请参阅的异步单元测试部分


我有几篇博客文章专门讨论异步单元测试。我为VS2010+AsyncCTP或VS11DevpReview编写了一个基本的异步单元测试项目,但我还没有机会用VS11Beta测试它。如果需要,这将是单元测试异步void方法的最简单方法

VS11 Beta对返回任务的测试方法具有一流的支持

因此,如果您将签名更改为:

public async static Task ExecuteNonQuery(string ConnStr, string Query)
然后您可以对其进行如下测试:

using Target = KC.DataAccess.Global.SQL;
[TestMethod]
[TestCategory("Unit")]
[ExpectedException(typeof(ArgumentNullException))]
public async Task ExecuteNonQueryFail1()
{
  await Target.ExecuteNonQuery(null, "select 1");
}
我自己还没有机会尝试这种新的支持,但我已经读到这应该是可行的

注意:除非必须返回void(例如,对于事件处理程序),否则应该在异步方法中返回Task。任务是可等待的,因此代码更易于重用。我把这件事写进去

如果出于某种原因确实需要测试异步void方法,则需要提供自己的SynchronizationContext来捕获任何异常。请参阅的异步单元测试部分


我有几篇博客文章专门讨论异步单元测试。我为VS2010+AsyncCTP或VS11DevpReview编写了一个基本的异步单元测试项目,但我还没有机会用VS11Beta测试它。如果需要,这将是单元测试异步void方法的最简单方法

注意:当我更改目标方法以返回任务时,以及当我在测试的配置文件中启用ThrowUnservedTaskExceptions时,会发生相同的行为。您应该使用TaskEx.Delay而不是Thread.Sleep。注意,当我更改目标方法以返回任务时,也会发生相同的行为,当我在测试的配置文件中启用ThrowUnobservedTaskException时,应该使用TaskEx.Delay而不是Thread.Sleep。如果使用Wait,则不能使用ExpectedException。将测试方法设为异步任务并让它等待任务将更干净。这是VS11Beta中添加的新功能;它不在VS11DevPreview中。您可以使用[ExpectedExceptiontypeofAggregateException],但我想这还不够具体。我确实有task/await的重载,但有些SQL调用可以随时执行。这是一个空白,因为我希望能够“触发并忘记”,就像在错误日志记录或将作业提交到队列的情况下一样。好的,我按照你说的做了,它抛出了AggregateException。这似乎不如抛出的实际异常有用,但至少我可以将其分解为聚合异常。现在,我如何保证它将以fire and forget的方式运行而不需要等待结果呢?很简单:该方法不返回任何结果,因此没有什么需要等待的。等待ExecuteOnQuery…根本无法编译。但是你真的不应该创建“开火然后忘记”的方法,除非你需要。这取决于消费者是否要等到完成。如果使用wait,则不能使用ExpectedException。将试验方法简化会更干净
c任务,并让它等待任务。这是VS11Beta中添加的新功能;它不在VS11DevPreview中。您可以使用[ExpectedExceptiontypeofAggregateException],但我想这还不够具体。我确实有task/await的重载,但有些SQL调用可以随时执行。这是一个空白,因为我希望能够“触发并忘记”,就像在错误日志记录或将作业提交到队列的情况下一样。好的,我按照你说的做了,它抛出了AggregateException。这似乎不如抛出的实际异常有用,但至少我可以将其分解为聚合异常。现在,我如何保证它将以fire and forget的方式运行而不需要等待结果呢?很简单:该方法不返回任何结果,因此没有什么需要等待的。等待ExecuteOnQuery…根本无法编译。但是你真的不应该创建“开火然后忘记”的方法,除非你需要。这取决于消费者是否愿意等待,直到完成。你的逻辑是正确的,但它仍然没有抛出。请参见svick的答案。您是否确实将Target.ExecuteNonQuery的返回类型更改为Task?将其包装到任务中。运行完全不是一回事。是的,我将其更改为任务。我所寻找的只是一种测试它、检测异常并能够运行它而无需在其他地方等待它的方法。很明显,我真的想在测试中等待它。你的逻辑是正确的,但它仍然没有抛出。请参见svick的答案。您是否确实将Target.ExecuteNonQuery的返回类型更改为Task?将其包装到任务中。运行完全不是一回事。是的,我将其更改为任务。我所寻找的只是一种测试它、检测异常并能够运行它而无需在其他地方等待它的方法。很明显,我真的想等待考试结果。