在 C# 中,我对 TryAsync 的负面测试有什么问题?

In C#, what is wrong with my negative test of TryAsync?

我有以下方法:

public TryAsync<bool> TryRelay(
    MontageUploadConfig montageData,
    File sourceFile,
    CancellationToken cancellationToken
) => new(async () =>
{
    byte[] fileContent = await _httpClient.GetByteArrayAsync(sourceFile.Url, cancellationToken);
    return await _attachmentController.TryUploadAttachment(montageData.EventId, fileContent, sourceFile.Name);
});

我创建了几个测试来证明它按预期工作。 我对负面案例的测试失败了。

这是测试:

[Fact]
public static async Task TestRelayShouldCatchErrorsGettingFile()
{
    // Arrange
    Mock<IAttachmentControllerV6> mockAttachmentController = new();
    Mock<HttpMessageHandler> mockHttpMessageHandler = new();
    MontageUploadTaskProcessor mockProcessorUnderTest = CreateProcessor(mockAttachmentController, mockHttpMessageHandler);

    MontageUploadConfig montageData = new()
    {
        EventId = "Test001"
    };
    File sourceFile = new()
    {
        Name = "Test.pdf",
        Url = "https://www.example.com/test.pdf"
    };
    CancellationToken cancellationToken = default;

    const string message = "Expected Exception";
    mockHttpMessageHandler.SetupAnyRequest()
        .Throws(new SalesforceCacheException(message));

    // Act
    Result<bool> result = await mockProcessorUnderTest.TryRelay(montageData, sourceFile, cancellationToken)();

    // Assert
    Assert.True(result.IsFaulted);
    result.IfFail(exception =>
    {
        Assert.True(exception is Exception);
        Assert.Equal(message, exception.Message);
    });
}

这是错误:

WorkflowTests.TaskProcessor.OldOrg.MontageUploadTaskProcessorUnitTests.TestRelayShouldCatchErrorsGettingFile Source: MontageUploadTaskProcessorUnitTests.cs line 59 Duration: 144 ms

Message: SFCacheController.SalesforceCacheException : Expected Exception

Stack Trace: ThrowException.Execute(Invocation invocation) line 22 MethodCall.ExecuteCore(Invocation invocation) line 97 Setup.Execute(Invocation invocation) line 85 FindAndExecuteMatchingSetup.Handle(Invocation invocation, Mock mock) line 107 IInterceptor.Intercept(Invocation invocation) line 17 Interceptor.Intercept(IInvocation underlying) line 107 AbstractInvocation.Proceed() HttpMessageHandlerProxy.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) HttpMessageInvoker.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) HttpClient.SendAsyncCore(HttpRequestMessage request, HttpCompletionOption completionOption, Boolean async, Boolean emitTelemetryStartStop, CancellationToken cancellationToken) HttpClient.GetByteArrayAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken) <b__0>d.MoveNext() line 140 --- End of stack trace from previous location --- MontageUploadTaskProcessorUnitTests.TestRelayShouldCatchErrorsGettingFile() line 81 --- End of stack trace from previous location ---

似乎在调用 TryRelay() 之后抛出异常,但甚至在尝试任何断言之前。

我期望 TryAsync 会捕获并框住异常是不是错了? 我期望它在测试环境中工作是错误的吗? 我需要做什么才能通过此测试?

您直接调用 TryAsync,它只是一个函数,因此除非您使用 TryAsync 上的扩展程序,否则它不会捕获任何内容,例如 Match

您可以做的是为您的单元测试构建一个辅助扩展:

public static Task<bool> HasFailed<E, A>(this TryAsync<A> ma) where E : Exception =>
    ma.Match(Succ: _ => false,
             Fail: e => e is E);

那你可以这样写:

TryAsync<X> ma = ...;

Assert.True(await ma.HasFailed<IOException, X>());