.NET 6(ASP.NET Core 6.0)从测试项目获取启动或程序集 [英] .NET 6 (ASP.NET Core 6.0) get Startup or Program Assembly from Test project

查看:0
本文介绍了.NET 6(ASP.NET Core 6.0)从测试项目获取启动或程序集的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在.NET Core 3.1和.NET 5中,我们有一个如下例所示的Xunit测试。它确保每个Controller都有一个AuthorizeAttribute以防止安全泄漏。

将我们的Web项目升级到ASP.NET Core 6的最小托管模型时,不再需要ProgramStartup类。除以下各项外,一切运行正常:

var types = typeof(Startup).Assembly.GetTypes();

查看命名空间Example.Web,我也看不到要从中加载程序集的任何类。如何在.NET 6中加载Program.cs程序集?

.NET 5中的示例:

using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using Xunit;

namespace Example.Web.Tests.ControllerTests
{
    public class AuthorizeAttributeTest
    {
        [Fact]
        public void ApiAndMVCControllersShouldHaveAuthorizeAttribute()
        {
            var controllers = GetChildTypes<ControllerBase>();
            foreach (var controller in controllers)
            {
                var attribute = Attribute.GetCustomAttribute(controller, typeof(Microsoft.AspNetCore.Authorization.AuthorizeAttribute), true) as Microsoft.AspNetCore.Authorization.AuthorizeAttribute;
                Assert.NotNull(attribute);
            }
        }

        private static IEnumerable<Type> GetChildTypes<T>()
        {
            var types = typeof(Startup).Assembly.GetTypes();
            return types.Where(t => t.IsSubclassOf(typeof(T)) && !t.IsAbstract);
        }
    }
}

推荐答案

简单的答案是,您可以在应用程序中引用任何(可访问)类,以便获得对程序集的引用。它不必是ProgramStartup类,也不必位于根命名空间中。

您显然希望选择一个期望持久的类,并且不会在以后的版本中被重命名或删除。从历史上看,Startup类符合该标准。然而,对于ASP.NET Core 6最小托管模型,这显然不再是真的。

鉴于此,您可以在此处采用两种方法。

选项1:将Assembly引用锚定在应用程序类之外

第一个选项是从应用程序中锚定任何任意的public类。例如,您可以使用其中一个控制器。只要它被编译到相同的程序集中,Assembly.GetTypes()调用将产生相同的结果。这可能类似于:

using Example.Web.Controllers;

var types = typeof(ExampleController).Assembly.GetTypes();

这种方法的主要缺点是类完全是任意的,将来可能会被移动或重命名。当然,如果确实发生了,您可能无论如何都需要更新您的单元测试,所以这不是什么大事。

选项2:向测试程序集公开Program

另一种选择是将Assembly引用锚定在从Program.cs文件编译的类之外,这与您之前的方法非常相似。这需要对编译器如何处理此文件有所了解。

当您使用ASP.NET Core 6最小托管模型时,您实际上是在利用C#9的顶级语句。编译器自动将任何顶级语句放入名为Program且没有命名空间的类中。

注意:与您使用的Program.cs不谋而合,但这完全是偶然的;您可以将Program.cs重命名为MyWebApplication.cs,但类仍将命名为Program

问题是此Program类被标记为internal,因此您的单元测试程序集无法访问。

但是,您可以通过将ASP.NET核心程序集的内部标记为对您的单元测试程序集可见来解决此问题。这可以通过将以下内容添加到您的AssemblyInfo.cs来实现:

[assembly: InternalsVisibleTo("Example.Web.Tests")]

或者,如@kal在注释中指出的,在csproj文件中设置以下内容:

<ItemGroup>
    <InternalsVisibleTo Include="Example.Web.Tests" />
</ItemGroup>

完成后,您可以使用以下命令访问Program类:

var types = typeof(Program).Assembly.GetTypes();

我不太喜欢以这种方式公开程序集的内部结构,但这是单元测试中相当常见的做法,因此我将其作为一个选项包括在内,以防您已经在这样做了。

最终,这与第一个选项没有什么不同-您仍然将Assembly引用锚定在不同的类上-但它的优势是锚定到一个我们知道将始终存在的类,而不是某个任意的、特定于应用程序的类。在阅读代码时,这可能也会感觉更直观。

这篇关于.NET 6(ASP.NET Core 6.0)从测试项目获取启动或程序集的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆