在 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>());
我有以下方法:
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>());