Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit testing that the swagger doc is correct without starting a server

I'd like to test that the swagger document is correct for my application (mainly, because I've added a strategy to generate custom OperationIds and I want to ensure they are correctly unique)

However, the only solutions I found are all using a "real" server (cf https://stackoverflow.com/a/52521454/1545567), which is not an option for me since I do not have the database, message bus, etc... when I launch the unit tests in CI...

At the moment, I have the following but it always generate 0 paths and 0 models ...

using FluentAssertions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
using SampleCheckIn;
using Swashbuckle.AspNetCore.SwaggerGen;
using System;
using System.Linq;
using Xunit;
using SampleCheckIn.Def;
using Service.Utils;
using Swashbuckle.AspNetCore.Swagger;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.FileProviders;

namespace D4Interop.Tests
{
    public class TmpTest
    {
        [Fact]
        public void Tmp()
        {
            var controllers = typeof(Startup).Assembly.GetTypes().Where(x => IsController(x)).ToList();
            controllers.Any().Should().BeTrue();

            var services = new ServiceCollection();
            controllers.ForEach(c => services.AddScoped(c));
            
            services.AddLogging(logging => logging.AddConsole());
            services.AddControllers(); //here, I've also tried AddMvcCore and other ASP methods...
            services.AddSwaggerGen(c =>
                {
                    c.SwaggerDoc("api", new OpenApiInfo { Title = Constants.SERVICE_NAME, Version = "_", Description = Constants.SERVICE_DESC });
                    //c.OperationFilter<SwaggerUniqueOperationId>(); //this is my filter that ensures the operationId is unique
                    c.CustomOperationIds(apiDesc =>
                    {
                        return apiDesc.TryGetMethodInfo(out var methodInfo) ? methodInfo.Name : null;
                    });
                });
            services.AddSingleton<IWebHostEnvironment>(new FakeWebHostEnvironment());
            var serviceProvider = services.BuildServiceProvider();


            var swaggerProvider = serviceProvider.GetRequiredService<ISwaggerProvider>();
            var swagger = swaggerProvider.GetSwagger("api");

            swagger.Should().NotBeNull();
            swagger.Paths.Any().Should().BeTrue();
        }

        private bool IsController(Type x)
        {
            return typeof(Microsoft.AspNetCore.Mvc.ControllerBase).IsAssignableFrom(x);
        }
    }

    internal class FakeWebHostEnvironment : IWebHostEnvironment
    {
        public FakeWebHostEnvironment()
        {
        }

        public IFileProvider WebRootFileProvider { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
        public string WebRootPath { get => "/root"; set => throw new NotImplementedException(); }
        public string EnvironmentName { get => "dev"; set => throw new NotImplementedException(); }
        public string ApplicationName { get => "app"; set => throw new NotImplementedException(); }
        public string ContentRootPath { get => "/"; set => throw new NotImplementedException(); }
        public IFileProvider ContentRootFileProvider { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
    }
}

like image 263
Christophe Blin Avatar asked Sep 16 '25 14:09

Christophe Blin


1 Answers

Ok, I've finally found that I just need to mix the linked answer with my code :

[Fact]
public async Task TestSwagger()
{
    var server = Host.CreateDefaultBuilder()
        .ConfigureWebHostDefaults(options => { options.UseStartup<Startup>(); })
        .Build();

    var swagger = server.Services
        .GetRequiredService<ISwaggerProvider>()
        .GetSwagger("xxx"); //xxx should be the name of your API

    swagger.Should().NotBeNull();
    swagger.Paths.Any().Should().BeTrue();
    swagger.Components.Schemas.Should().NotBeNull();
}
like image 71
Christophe Blin Avatar answered Sep 19 '25 08:09

Christophe Blin