aspnet / AspNetWebStack

ASP.NET MVC 5.x, Web API 2.x, and Web Pages 3.x (not ASP.NET Core)
Other
858 stars 354 forks source link

How to test returned `Unauthorized()`? #285

Closed Regenhardt closed 3 years ago

Regenhardt commented 4 years ago

I'm trying to unit teset a controller method that, in specific circumstances, returns an Unauthorized(). For this, I have a pretty simple unit test:

// Arrange
var service1Mock = Substitute.For<IService1>();
var service2Mock = Substiture.For<IService2>();
[ Mock a method for service1 that will be called to return invalid data for id == -1]
var controllerUnderTest = new MyController(service1Mock, service2Mock)
{
  Request = new HttpRequestMessage(),
  Configuration = new HttpConfiguration()
}
var data = new Dto() { Id= -1 };

// This setup will prompt MyController.ControllerMethod to `return this.Unauthorized();`
// Act
var result = await controllerUnderTest.ControllerMethod().ExecuteAsync(CancellationToken.None); // it fails here

// Assert
Assert.That(result.IsSuccessStatusCode, Is.False);
Assert.That(result.StatusCode, Is.EqualTo(HttpStatusCode.Unauthorized));

The test runs flawlessly when debugging. When run in NCrunch, it will fail every second time, returning a 500 InvalidServerError. When run on the server in the CI pipeline, it will fail every time, crashing with the following stacktrace:

System.InvalidOperationException : HttpControllerContext.Configuration must not be null.
bei System.Web.Http.Results.ExceptionResult.ApiControllerDependencyProvider.EnsureResolved()
bei System.Web.Http.Results.ExceptionResult.ApiControllerDependencyProvider.get_IncludeErrorDetail()
bei System.Web.Http.Results.ExceptionResult.Execute()
bei System.Web.Http.Results.ExceptionResult.ExecuteAsync(CancellationToken cancellationToken) 

How is this even possible? DO I have to mock something else to properly test an ApiController?

We're on netFx462, System.Web.Http 5.2.7.0, using NUnit to test and NCrunch Console Tool for pipeline tests. Every test except this one works. Even other tests for this particular method. Only the Unauthorized one fails.

mkArtakMSFT commented 3 years ago

Thanks for contacting us. While we sympathize with you and this is frustrating to see, it's not something we plan to prioritize to investigate as this is not a production scenario.

Regenhardt commented 3 years ago

I'm not sure how you determined that, but this is absolutely a production scenario. Our application has way too much logic within the controller that needs to be tested. Were this not a production scenario, I'd immediately update to .NET, but the application is just too big to do that.