JasperFx / alba

Easy integration testing for ASP.NET Core applications
https://jasperfx.github.io/alba
Apache License 2.0
405 stars 39 forks source link

Asserting action which throws exception #95

Closed Samuel-Langlois-BimOne closed 2 years ago

Samuel-Langlois-BimOne commented 3 years ago

I'm trying to test an action which throws an exception. I would have expected that I could run the scenario and check for the response code (500 or otherwise), but the test fails before that.

In the test I just get the URL:

return Application.AlbaHost.Scenario(
  _ =>
  {
      _.Get.Url("/Hub");
  });

The tested action just throws an error

  public Task<ActionResult<Hub>> Index()
  {
      throw new NotFoundException("Hub not found");
  }

Here is the call stack.

System.IO.IOException : No message provided
  ----> BIMTrack.BIAnalytics.Core.Exceptions.NotFoundException : Hub not found
   at Microsoft.AspNetCore.TestHost.ResponseBodyReaderStream.CheckAborted()
   at Microsoft.AspNetCore.TestHost.ResponseBodyReaderStream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.TestHost.ResponseBodyReaderStream.Read(Byte[] buffer, Int32 offset, Int32 count)
   at Baseline.StreamExtensions.ReadAllBytes(Stream stream)
   at Alba.ScenarioAssertionException.ReadBody(HttpContext context)
   at Alba.Assertions.StatusCodeAssertion.Assert(Scenario scenario, HttpContext context, ScenarioAssertionException ex)
   at Alba.Scenario.RunAssertions(HttpContext context)
   at Alba.AlbaHost.Scenario(Action`1 configure)
   at Alba.AlbaHost.Scenario(Action`1 configure)
   at BiAnalytics.Service.IntegrationTests.HubTests.Get_WithNonExistingHub_ShouldReturnError() in C:\git\PhareBI-ClientManagement\BiAnalyticsService\BiAnalytics.Service.IntegrationTests\HubTests.cs:line 90
   at NUnit.Framework.Internal.TaskAwaitAdapter.GenericAdapter`1.BlockUntilCompleted()
   at NUnit.Framework.Internal.MessagePumpStrategy.NoMessagePumpStrategy.WaitForCompletion(AwaitAdapter awaiter)
   at NUnit.Framework.Internal.AsyncToSyncAdapter.Await(Func`1 invoke)
   at NUnit.Framework.Internal.Commands.TestMethodCommand.RunTestMethod(TestExecutionContext context)
   at NUnit.Framework.Internal.Commands.TestMethodCommand.Execute(TestExecutionContext context)
   at NUnit.Framework.Internal.Commands.BeforeAndAfterTestCommand.<>c__DisplayClass1_0.<Execute>b__0()
   at NUnit.Framework.Internal.Commands.BeforeAndAfterTestCommand.RunTestMethodInThreadAbortSafeZone(TestExecutionContext context, Action action)
--NotFoundException
   at BIMTrack.BIAnalytics.Core.BusinessRules.HubBusinessRules.GetByIdAsync(String hubId) in C:\git\PhareBI-ClientManagement\BiAnalyticsService\BIAnalytics.Core\BusinessRules\HubBusinessRules.cs:line 26
   at BIMTrack.BiAnalytics.Service.Controllers.HubController.Index() in C:\git\PhareBI-ClientManagement\BiAnalyticsService\BIAnalytics.Service\Controllers\HubController.cs:line 37
   at lambda_method35(Closure , Object )
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Logged|12_1(ControllerActionInvoker invoker)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at Swashbuckle.AspNetCore.ReDoc.ReDocMiddleware.Invoke(HttpContext httpContext)
   at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
   at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.HandleException(HttpContext context, ExceptionDispatchInfo edi)
   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
   at Microsoft.AspNetCore.TestHost.HttpContextBuilder.<>c__DisplayClass23_0.<<SendAsync>g__RunRequestAsync|0>d.MoveNext()

I use an exception handler middleware. I tried without it, and it throws the NotFoundException directly instead, but it still throws an exception.

Tested with Alba 5.0.1

jeremydmiller commented 3 years ago

@Samuel-Langlois-BimOne Sorry for being so slow answering this, but I think that's Alba working exactly as expected. Try:

return Application.AlbaHost.Scenario( => { .Get.Url("/Hub"); ..StatusCodeShouldBe(500); });

with the exception middleware on.

jeremydmiller commented 2 years ago

@Samuel-Langlois-BimOne I played with this a bit today. I think there's something else going on in your middleware that was making Alba wonky with the response body. Regardless, I hardened the area of the Alba code that was throwing during the assertion message to stop this from happening again. I did verify that the status code assertion is working at least.

Samuel-Langlois-BimOne commented 2 years ago

@jeremydmiller Thanks for checking. Not sure what was going on, but it turns out that just upgrading to .NET 6 fixed the issue 😮. I also upgraded to the latest Alba version and everything works well !