I have an ErrorController:
public class ErrorController : Controller
{
private readonly ILogger<ErrorController> _logger;
public ErrorController(ILogger<ErrorController> logger)
{
_logger = logger;
}
[Route("/Error/{statusCode}")]
public IActionResult HttpStatusCodeHandler(int statusCode)
{
var statusCodeResult = HttpContext.Features.Get<IStatusCodeReExecuteFeature>();
switch (statusCode)
{
case 400:
ViewBag.ErrorMessage = "Bad Request. The server could not understand the request.";
_logger.LogWarning($"400 Error Occurred. Path = {statusCodeResult.OriginalPath}" +
$" and QueryString = {statusCodeResult.OriginalQueryString}");
break;
case 401:
ViewBag.ErrorMessage = "Unauthorized. You are not authorized to access the requested resource.";
_logger.LogWarning($"401 Error Occurred. Path = {statusCodeResult.OriginalPath}" +
$" and QueryString = {statusCodeResult.OriginalQueryString}");
break;
case 403:
ViewBag.ErrorMessage = "Forbidden. You do not have permission to access the requested resource.";
_logger.LogWarning($"403 Error Occurred. Path = {statusCodeResult.OriginalPath}" +
$" and QueryString = {statusCodeResult.OriginalQueryString}");
break;
case 404:
ViewBag.ErrorMessage = "Not Found. The resource you requested could not be found.";
_logger.LogWarning($"404 Error Occurred. Path = {statusCodeResult.OriginalPath}" +
$" and QueryString = {statusCodeResult.OriginalQueryString}");
break;
case 500:
ViewBag.ErrorMessage = "Internal Server Error. An unexpected error occurred on the server.";
_logger.LogError($"500 Error Occurred. Path = {statusCodeResult.OriginalPath}" +
$" and QueryString = {statusCodeResult.OriginalQueryString}");
break;
default:
ViewBag.ErrorMessage = "An error occurred while processing your request.";
_logger.LogError($"Error {statusCode} occurred. Path = {statusCodeResult.OriginalPath}" +
$" and QueryString = {statusCodeResult.OriginalQueryString}");
break;
}
return View("Error");
}
[Route("/Error")]
public IActionResult ErrorHandler()
{
var statusCodeResult = HttpContext.Features.Get<IStatusCodeReExecuteFeature>();
if(statusCodeResult != null)
{
var statusCodeResultErrorMessage = $"Error occurred. Path = {statusCodeResult.OriginalPath} and QueryString = {statusCodeResult.OriginalQueryString}";
_logger.LogError(statusCodeResultErrorMessage);
}
ViewBag.ErrorMessage = "Sorry, an error occurred.";
return View("Error");
}
}
I am trying to unit test it using XUnit and Moq. Here are my unit tests:
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.Extensions.Logging;
namespace UnitTests;
public class ErrorControllerTests
{
[Fact]
public void HttpStatusCodeHandler_ReturnsViewWithErrorMessage_For404()
{
// Arrange
var loggerMock = new Mock<ILogger<ErrorController>>();
var controller = new ErrorController(loggerMock.Object);
var httpContext = new DefaultHttpContext();
var routeData = new RouteData();
routeData.Values["statusCode"] = 404;
var actionContext = new ActionContext(httpContext, routeData, new ControllerActionDescriptor());
controller.ControllerContext = new ControllerContext(actionContext);
// Act
var result = controller.HttpStatusCodeHandler(404) as ViewResult;
// Assert
Assert.NotNull(result);
Assert.Equal("Error", result.ViewName);
Assert.Equal("Sorry, the resource you requested could not be found.", result.ViewData["ErrorMessage"]);
// Verify logging
loggerMock.Verify(logger => logger.LogError("Resource not found. Status code: 404"), Times.Once);
}
[Fact]
public void HttpStatusCodeHandler_ReturnsViewWithGenericErrorMessage_ForOtherStatusCodes()
{
// Arrange
var loggerMock = new Mock<ILogger<ErrorController>>();
var controller = new ErrorController(loggerMock.Object);
var httpContext = new DefaultHttpContext();
var routeData = new RouteData();
routeData.Values["statusCode"] = 500;
var actionContext = new ActionContext(httpContext, routeData, new ControllerActionDescriptor());
controller.ControllerContext = new ControllerContext(actionContext);
// Act
var result = controller.HttpStatusCodeHandler(500) as ViewResult;
// Assert
Assert.NotNull(result);
Assert.Equal("Error", result.ViewName);
Assert.Equal("An error occurred while processing your request.", result.ViewData["ErrorMessage"]);
// Verify logging
loggerMock.Verify(logger => logger.LogError("An error occurred. Status code: 500"), Times.Once);
}
}
However, I don't understand how to declare the "RouteData()"? I am getting the following error in my code (and it won't build).
The RouteData error is "There is no argument given that responds to the required parameter of pageType of 'RouteData.RouteData(Type, IReadOnlyDictionary<string, object?>)'"
Any help would be greatly appreciated, thank you.
I was using an incorrect namespace of "Microsoft.AspNetCore.Components", but it should have been "Microsoft.AspNetCore.Routing". Resolved.