Как заменить Middleware в проекте интеграционных тестов - PullRequest
0 голосов
/ 02 сентября 2018

У меня есть автозагрузка cs, где я регистрирую AuthenticationMiddleware следующим образом:

public class Startup
{
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        ...
        AddAuthentication(app);
        app.UseMvcWithDefaultRoute();
        app.UseStaticFiles();
    }

    protected virtual void AddAuthentication(IApplicationBuilder app)
    {
        app.UseAuthentication();
    }
}

и я проверяю это с помощью:

WebApplicationFactory<Startup>().CreateClient();

Вопрос:

Я хотел бы заменить app.UseAuthentication(); на app.UseMiddleware<TestingAuthenticationMiddleware>(),

Что я пробовал:

Я думал о наследовании от автозагрузки в моем тестовом проекте:

public class TestStartup : Startup
{
    protected override void AddAuthentication(IApplicationBuilder app)
    {
        app.UseMiddleware<AuthenticatedTestRequestMiddleware>();
    }
}

class TestWebApplicationFactory : WebApplicationFactory<Web.Startup>
{
    protected override IWebHostBuilder CreateWebHostBuilder()
    {
        return WebHost.CreateDefaultBuilder()
            .UseStartup<IntegrationTestProject.TestStartup>();
    }
}

но это не работает, поскольку TestStartup находится в другой сборке, которая имеет множество побочных эффектов для WebHost.CreateDefaultBuilder()

Я получаю:

System.ArgumentException: корень содержимого «C: \ Projects \ Liero \ myproject \ tests \ IntegrationTests» не существует. Имя параметра: contentRootPath

Ответы [ 2 ]

0 голосов
/ 16 сентября 2018

Кажется, что WebApplicationFactory должен использовать реальный класс Startup в качестве аргумента типа:

class TestWebApplicationFactory : WebApplicationFactory<Startup>
{
    protected override IWebHostBuilder CreateWebHostBuilder()
    {
        return WebHost.CreateDefaultBuilder<TestableStartup>(new string[0]);
    }
}
0 голосов
/ 02 сентября 2018

Я столкнулся с той же проблемой и решил ее так;

 /// <summary>
    /// A test fixture which hosts the target project (project we wish to test) in an in-memory server.
    /// </summary>
    /// <typeparam name="TStartup">Target project's startup type</typeparam>
    /// <typeparam name="DStartup">Decorated startup type</typeparam>
    public class TestFixture<DStartup, TStartup> : IDisposable
    {
        private readonly TestServer _server;

        public TestFixture()
            : this(Path.Combine("YourRelativeTargetProjectParentDir"))
        {
        }

        protected TestFixture(string relativeTargetProjectParentDir)
        {
            var startupAssembly = typeof(TStartup).GetTypeInfo().Assembly;
            var contentRoot = GetProjectPath(relativeTargetProjectParentDir, startupAssembly);

            //var integrationTestsPath = PlatformServices.Default.Application.ApplicationBasePath;
            //var contentRoot = Path.GetFullPath(Path.Combine(integrationTestsPath, "../../../../MinasTirith"));
            var builder = new WebHostBuilder()
                .UseContentRoot(contentRoot)
                .ConfigureServices(InitializeServices)
                .UseEnvironment("Development")
                .UseStartup(typeof(DStartup));

            _server = new TestServer(builder);

            Client = _server.CreateClient();
            Client.BaseAddress = new Uri("http://localhost:5000");
        }

        public HttpClient Client { get; }   

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            Client.Dispose();
            _server.Dispose();
        }


        protected virtual void InitializeServices(IServiceCollection services)
        {
            var startupAssembly = typeof(TStartup).GetTypeInfo().Assembly;

            // Inject a custom application part manager. 
            // Overrides AddMvcCore() because it uses TryAdd().
            var manager = new ApplicationPartManager();
            manager.ApplicationParts.Add(new AssemblyPart(startupAssembly));
            manager.FeatureProviders.Add(new ControllerFeatureProvider());
            manager.FeatureProviders.Add(new ViewComponentFeatureProvider());

            services.AddSingleton(manager);
        }

        /// <summary>
        /// Gets the full path to the target project that we wish to test
        /// </summary>
        /// <param name="projectRelativePath">
        /// The parent directory of the target project.
        /// e.g. src, samples, test, or test/Websites
        /// </param>
        /// <param name="startupAssembly">The target project's assembly.</param>
        /// <returns>The full path to the target project.</returns>
        private static string GetProjectPath(string projectRelativePath, Assembly startupAssembly)
        {
            // Get name of the target project which we want to test
            var projectName = startupAssembly.GetName().Name;

            // Get currently executing test project path
            var applicationBasePath = System.AppContext.BaseDirectory;

            // Find the path to the target project
            var directoryInfo = new DirectoryInfo(applicationBasePath);
            do
            {
                directoryInfo = directoryInfo.Parent;

                var projectDirectoryInfo = new DirectoryInfo(Path.Combine(directoryInfo.FullName, projectRelativePath));
                if (projectDirectoryInfo.Exists)
                {
                    var projectFileInfo = new FileInfo(Path.Combine(projectDirectoryInfo.FullName, projectName, $"{projectName}.csproj"));
                    if (projectFileInfo.Exists)
                    {
                        return Path.Combine(projectDirectoryInfo.FullName, projectName);
                    }
                }
            }
            while (directoryInfo.Parent != null);

            throw new Exception($"Project root could not be located using the application root {applicationBasePath}.");
        }
    }

И я использую его в своих методах модульного тестирования, как это;

    [TestInitialize]
    public void BeforeEachTest()
    {
        testFixture = new TestFixture<TestStartup, Startup>();
        //this is my HttpClient variable
        client = testFixture.Client;
    }

P.S. Это точный фрагмент кода, который я использую для своего проекта.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...