Skip to content

Instantly share code, notes, and snippets.

@AMCN41R
Last active June 6, 2020 11:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AMCN41R/7331c282a60c46f1b9ee5a0fc0933d9a to your computer and use it in GitHub Desktop.
Save AMCN41R/7331c282a60c46f1b9ee5a0fc0933d9a to your computer and use it in GitHub Desktop.
C# Controller Unit Test Assertion Helpers
namespace TestHelpers
{
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Routing;
/// <summary>
/// A set of methods to aid C# Controller unit test assertions.
/// </summary>
public static class AssertController
{
/// <summary>
/// Verifies that a controller has the <see cref="RouteAttribute"/> with the correct template.
/// </summary>
/// <typeparam name="TController">The controller to verify.</typeparam>
/// <param name="route">The expected route.</param>
public static void HasRouteAttribute<TController>(string route)
where TController : ControllerBase
{
var attr = typeof(TController).GetCustomAttributes(typeof(RouteAttribute), false).ToList();
attr.AssertAttributeCount<RouteAttribute>();
Xunit.Assert.Equal(route.ToLower(), ((RouteAttribute)attr[0]).Template.ToLower());
}
/// <summary>
/// Verifies that a controller method has the correct <see cref="HttpMethodAttribute"/>.
/// </summary>
/// <typeparam name="TController">The controller that contains the method to verify.</typeparam>
/// <typeparam name="TVerbAttribute">The expected verb attribute.</typeparam>
/// <param name="methodName">The name of the method to verify.</param>
public static void MethodHasVerb<TController, TVerbAttribute>(string methodName)
where TController : ControllerBase
where TVerbAttribute : HttpMethodAttribute
{
var method = typeof(TController).GetMethod(methodName);
var attr = method?.GetCustomAttributes(typeof(TVerbAttribute), false).ToList();
attr.AssertAttributeCount<TVerbAttribute>();
}
/// <summary>
/// Verifies that a controller method has the correct <see cref="HttpMethodAttribute"/> with the correct route template.
/// </summary>
/// <typeparam name="TController">The controller that contains the method to verify.</typeparam>
/// <typeparam name="TVerbAttribute">The expected verb attribute.</typeparam>
/// <param name="methodName">The name of the method to verify.</param>
/// <param name="template">The expected route template.</param>
public static void MethodHasVerb<TController, TVerbAttribute>(string methodName, string template)
where TController : ControllerBase
where TVerbAttribute : HttpMethodAttribute
{
var method = typeof(TController).GetMethod(methodName);
var attr = method?.GetCustomAttributes(typeof(TVerbAttribute), false).ToList();
if (attr == null)
{
throw new Exception("No custom attributes found.");
}
attr.AssertAttributeCount<TVerbAttribute>();
var verb = (HttpMethodAttribute)attr[0];
Xunit.Assert.Equal(template, verb.Template);
}
private static void AssertAttributeCount<T>(this ICollection<object> attr)
where T : Attribute
{
var baseMessage = $"Assert has {typeof(T).Name} attribute failure.";
if (attr.Count == 0)
{
throw new Exception($"{baseMessage} No such attribute.");
}
if (attr.Count > 1)
{
throw new Exception(
$"{baseMessage} Attribute should exist once but exists {attr.Count} times.");
}
}
}
}
[Route("api/orders")]
public class OrderController : ControllerBase
{
[HttpGet]
public async Task<IActionResult> GetOrders()
{
// implementation
}
[HttpGet("{orderId}/products")]
public async Task<IActionResult> GetProductsForOrder(Guid orderId)
{
// implementation
}
}
public class OrderControllerTests
{
[Fact]
public void Controller_RouteAttribute_IsPresentWIthCorrectRoute()
{
AssertController.HasRouteAttribute<OrderController>("api/orders");
}
[Fact]
public void GetOrders_Method_HasCorrectVerbAttribute()
{
AssertController
.MethodHasVerb<OrderController, HttpGetAttribute>(
nameof(OrderController.GetOrders)
);
}
[Fact]
public void GetProductsForOrder_Method_HasCorrectVerbAttributeAndPath()
{
AssertController
.MethodHasVerb<OrderController, HttpGetAttribute>(
nameof(OrderController.GetProductsForOrder),
"{orderId}/products"
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment