异步方法中的单元测试异常

时间:2019-12-17 02:21:35

标签: c# exception async-await vstest

我正在尝试使用VSTest在下面对异步方法进行单元测试。但是,即使仅在第一种情况下引发了异常,{ "errorMessage": "java.util.Optional cannot be cast to com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent", "errorType": "java.lang.ClassCastException", "stackTrace": [ "com.transformco.hs.css.userprofile.function.UserProfileFunction.apply(UserProfileFunction.java:16)", "org.springframework.cloud.function.context.catalog.BeanFactoryAwareFunctionRegistry$FunctionInvocationWrapper.invokeFunction(BeanFactoryAwareFunctionRegistry.java:499)", "org.springframework.cloud.function.context.catalog.BeanFactoryAwareFunctionRegistry$FunctionInvocationWrapper.lambda$doApply$1(BeanFactoryAwareFunctionRegistry.java:543)", "reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:107)", "reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:121)", "reactor.core.publisher.FluxJust$WeakScalarSubscription.request(FluxJust.java:99)", "reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.request(FluxMapFuseable.java:162)", "reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.request(FluxMapFuseable.java:162)", "reactor.core.publisher.BlockingIterable$SubscriberIterator.onSubscribe(BlockingIterable.java:218)", "reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onSubscribe(FluxMapFuseable.java:90)", "reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onSubscribe(FluxMapFuseable.java:90)", "reactor.core.publisher.FluxJust.subscribe(FluxJust.java:70)", "reactor.core.publisher.InternalFluxOperator.subscribe(InternalFluxOperator.java:53)", "reactor.core.publisher.BlockingIterable.iterator(BlockingIterable.java:80)", "org.springframework.cloud.function.adapter.aws.SpringBootRequestHandler.result(SpringBootRequestHandler.java:59)", "org.springframework.cloud.function.adapter.aws.SpringBootRequestHandler.handleRequest(SpringBootRequestHandler.java:52)", "org.springframework.cloud.function.adapter.aws.SpringBootApiGatewayRequestHandler.handleRequest(SpringBootApiGatewayRequestHandler.java:140)", "org.springframework.cloud.function.adapter.aws.SpringBootApiGatewayRequestHandler.handleRequest(SpringBootApiGatewayRequestHandler.java:43)" ] } AsyncMathsStatic.Divide(4, 0)的测试仍通过。

AsyncMathsStatic.Divide(4, 1))

3 个答案:

答案 0 :(得分:2)

重要的是要了解异步方法是如何工作的,以了解发生了什么。与所有其他方法一样,所有异步方法都开始同步运行。但是在对不完整的await起作用的第一个Task处,该方法返回。通常,它将返回自己的Task,呼叫者随后可以等待。

但是,如果方法签名为async void,则它不返回任何内容。此时,该方法尚未完成运行,但是调用方法将永远不知道何时或是否完成。

这可能是这里发生的事情。该方法返回第一个await时返回,并且认为测试成功完成。它永远不会看到以后会抛出的异常。

解决方法是返回Task,以便可以等待该方法:

public static async Task Divide(int v1, int v2)

async void的唯一合法用途是用于事件处理程序,因为您别无选择,只能使它们void。但是通常也可以,因为事件应该是“哦,顺便说一句”,并且成功完成事件处理程序通常不会影响调用它的操作(但是有一些例外)

答案 1 :(得分:0)

如果您的测试环境不允许使用异步测试方法,请使用以下内容:

       [TestMethod]
    public void TestMethod1()
    {
        Task.Run(async () =>
        {
           // test setup

            var result = await SomeAsyncTask();
            Assert.IsTrue(result.Id != 0, "Id not changed");

        }).GetAwaiter().GetResult();
    }

@Paulo指出,如果您的测试环境允许异步测试方法,则可以使用:

      [TestMethod]
    public async Task TestMethod1()
    {
       // test setup

        var result = await SomeAsyncMethod();
        Assert.IsTrue(result.Id != 0, "Id not changed");
    }

答案 2 :(得分:0)

即使该方法是同步的,执行也将一直同步,直到第一次等待未完成的任务为止。您的代码甚至没有await

async void方法是无法等待的。

该方法将返回一个未等待的任务,就像该方法是async void

以下代码显示了所有这些情况:

static async Task Main()
{
    try
    {
        Console.WriteLine("Before calling "+ nameof(AsyncMathsStatic.Divide1));
        var t = AsyncMathsStatic.Divide1(4, 0);
        Console.WriteLine("After calling "+ nameof(AsyncMathsStatic.Divide1));
        await t;
    }
    catch (DivideByZeroException ex)
    {
        Console.WriteLine("Exception thrown in " + nameof(Main));
    }

    try
    {
        Console.WriteLine("Before calling "+ nameof(AsyncMathsStatic.Divide2));
        var t = AsyncMathsStatic.Divide2(4, 0);
        Console.WriteLine("After calling "+ nameof(AsyncMathsStatic.Divide2));
        await t;
    }
    catch (DivideByZeroException ex)
    {
        Console.WriteLine("Exception thrown in " + nameof(Main));
    }
}

public class AsyncMathsStatic
{
    public static async Task Divide1(int v1, int v2)
    {
        try
        {
            Console.WriteLine(nameof(Divide1) + ".1");
            await Task.Yield();
            Console.WriteLine(nameof(Divide1) + ".2");
            if (v1 / v2 > 1)
            {
                await Task.Yield();
            }
        }
        catch (DivideByZeroException ex)
        {
            Console.WriteLine("Exception thrown in " + nameof(Divide1));
            throw;
        }
    }
    public static async Task Divide2(int v1, int v2)
    {
        try
        {
            Console.WriteLine(nameof(Divide2) + ".1");
            await Task.CompletedTask;
            Console.WriteLine(nameof(Divide2) + ".2");
            if (v1 / v2 > 1)
            {
                await Task.Yield();
            }
        }
        catch (DivideByZeroException ex)
        {
            Console.WriteLine("Exception thrown in " + nameof(Divide2));
            throw;
        }
    }
}

/* Output
Before calling Divide1
Divide1.1
After calling Divide1
Divide1.2
Exception thrown in Divide1
Exception thrown in Main
Before calling Divide2
Divide2.1
Divide2.2
Exception thrown in Divide2
After calling Divide2
Exception thrown in Main
*/

这证明,如果与您发布的内容完全一样,您应该抛出该东西。

我在这里想念东西吗?