1

I want to build integration tests to make sure all of our endpoints are locked behind authentication.

I will then fetch all of our endpoints from our swagger. How can i await this call and then use this data as memberData or classData? Since it's async. Should i use fixtures, or some kind of ----Data?

    [Collection("A collection")]
    public class EndpointsTests
    {
        RouteDataFixture fixture;

        public EndpointsTests(RouteDataFixture fixture)
        {
            this.fixture = fixture;
        }

        [Theory]
        [ClassData(typeof(SomeClassWithAsyncConstructor))]
        public async Task Test_This(string path, string method)
        {
            //test the awaited data from class
            if(method == "GET"=
                var response = await fixture.GetAsync(path)

            //Check if the response is unauthorized since we didn't send a token
        }
    }
Nkosi
  • 235,767
  • 35
  • 427
  • 472
LittleMygler
  • 632
  • 10
  • 24

1 Answers1

4

If there is no special reason you can use unit test instead of integration test and you can check your endpoints defined or not defined any authorization attribute. For example;

    public class SomeController : Controller
    {
        [AllowAnonymous]
        public IAsyncResult Post1()
        {
            // codes...
        }

        [Authorize("some_permission")]
        public IAsyncResult Post2()
        {
            // codes...
        }

        public IAsyncResult Post3()
        {
            // codes...
        }
    }

this is your controller class.

    [Fact]
    public void Test()
    {
        var _endpoints = new List<(Type, MethodInfo)>(); // All endpoints in my project
        var asm = Assembly.Load("MyAssembly");
        var cType = typeof(Controller);
        var types = asm.GetTypes().Where(x => x.IsSubclassOf(cType)).ToList();
        foreach (Type t in types)
        {
            var mInfos = t.GetMethods(BindingFlags.Public | BindingFlags.Instance).Where(x => x.DeclaringType.Equals(t)).ToList();
            foreach (MethodInfo mInfo in mInfos)
                _endpoints.Add((t, mInfo));
        }

        var nonAuthEndPoints = _endpoints.Where(x => !x.IsDefined(typeof(AuthorizeAttribute)) && !x.IsDefined(typeof(AllowAnonymousAttribute)));

        nonAuthEndPoints.Should().BeEmpty();
    }

and this is your test method. This would check all endpoints and force they should have AllowAnonymous or Authorize.

In this example your Post1 and Post2 endpoints passed the test but post3 failed.

Emre HIZLI
  • 513
  • 6
  • 14
  • 1
    Consider using a more abstract base class `ControllerBase` since not all will be derived from `Controller` ie: API controllers. – Nkosi Mar 16 '20 at 12:54
  • the point of fetching from swagger was to get all endpoints and don't need to update the test everytime. What is "MyAssembly" in this context? – LittleMygler Mar 16 '20 at 13:01
  • Its your project assembly. I am talking about in .net stack for this answer – Emre HIZLI Mar 16 '20 at 13:16
  • You can filter types with their namespaces. Where(x => x.IsSubclassOf(cType) && x.Namespace == "Your namespace") – Emre HIZLI Mar 16 '20 at 13:31
  • Yea i noticed thanks! Another question though. The filter seems to only filter out where the controller does AllowAnonymous, but I also want where the actions does too :) – LittleMygler Mar 16 '20 at 13:34
  • solved it, thanks for your help dude! Really appreciate it! – LittleMygler Mar 16 '20 at 13:40