using System.Reflection; using System.Text; using eSuite.API.security; using eSuite.API.Utilities; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Routing; using NUnit.Framework; namespace eSuite.API.UnitTests.Controllers.MiscellaniousUnitTests; [TestFixture] public class ControllerUnitTests { private static IEnumerable GetAllControllers() { var referencedAssemblies = Assembly.GetExecutingAssembly().GetReferencedAssemblies(); var esuiteAPi = referencedAssemblies.Single(assembly => assembly.Name == "eSuite.API"); var assembly = Assembly.Load(esuiteAPi); var controllers = assembly .GetTypes() .Where(type => typeof(ControllerBase).IsAssignableFrom(type) && !type.IsAbstract); return controllers; } private static CustomAttributeData? FindAttribute(MethodInfo publicMethod, Type type) { return publicMethod.CustomAttributes.FirstOrDefault(customAttribute => type.IsAssignableFrom(customAttribute.AttributeType)); } private static bool ImplementsParameterByType(MethodInfo publicMethod, Type type) { return publicMethod.GetParameters().Any(parameter => type.IsAssignableFrom(parameter.ParameterType)); } [Test] public void Controller_Implemented_IsInheritedFromESuiteControllerBase() { //Arrange var controllers = GetAllControllers(); Assert.That(controllers.Count(), Is.GreaterThan(0)); //Act foreach (var controller in controllers) if (!(typeof(ESuiteControllerBase).IsAssignableFrom(controller) || typeof(ESuiteController).IsAssignableFrom(controller))) //Assert Assert.Fail($"{controller.FullName} is not {typeof(ESuiteControllerBase)} or {typeof(ESuiteController)}"); } [Test] public void Controller_EveryMethod_ImplementsCancellationToken() { //Arrange var controllers = GetAllControllers(); foreach (var controller in controllers) { var publicMethods = controller.GetMethods().Where(method => method.IsPublic).ToArray(); //Act foreach (var publicMethod in publicMethods) { var attribute = FindAttribute(publicMethod, typeof(HttpMethodAttribute)); if (attribute == null) continue; if (!ImplementsParameterByType(publicMethod, typeof(CancellationToken))) //Assert Assert.Fail($"{controller.Name}.{publicMethod.Name} does not have a {typeof(CancellationToken)} parameter"); } //Assert Assert.That(publicMethods.Length, Is.GreaterThan(0)); } } [Test] public void Controller_EveryMethod_HasAccessKeyAttribute() { //Arrange var errors = new List(); var controllers = GetAllControllers(); foreach (var controller in controllers) { var publicMethods = controller.GetMethods().Where(method => method.IsPublic).ToArray(); //Act foreach (var publicMethod in publicMethods) { var attribute = FindAttribute(publicMethod, typeof(HttpMethodAttribute)); if (attribute == null) continue; var accessKeyAttribute = FindAttribute(publicMethod, typeof(AccessKeyAttribute)); if (accessKeyAttribute == null) { var allowAnonymousAttribute = FindAttribute(publicMethod, typeof(AllowAnonymousAttribute)); if (allowAnonymousAttribute != null) continue; errors.Add($"{controller.Name}.{publicMethod.Name} does not have an AccessKeyAttribute"); } } //Assert Assert.That(publicMethods.Count, Is.GreaterThan(0)); } Assert.Multiple(() => { if (errors.Count > 0) { var sb = new StringBuilder(); foreach (var error in errors) { sb.AppendLine(error); } Assert.Fail(sb.ToString()); } }); } }