使用PrincipalContext(Windows身份验证)时如何进行集成测试?

时间:2020-01-21 15:22:01

标签: asp.net-core integration-testing moq windows-authentication xunit.net

我有一个具有Windows身份验证的Intranet ASP核心3.0 MVC Web应用程序。 在Views / Shared / _Layout中,我使用以下方法调用ViewCompent以获取当前用户的名字和姓氏:

    public Task<string> getNameAsync()
    {
        return Task.Run<string>(() =>
        {
            string name = GetNameInSession();
            if (name == null || name == "")
            {
                PrincipalContext pc = new PrincipalContext(ContextType.Domain);
                UserPrincipal user = UserPrincipal.FindByIdentity(pc, User.Identity.Name);
                name = user.GivenName + " " + user.Surname;
                SetNameInSession(name);
            }
            return name;
        });
    }

我目前正在尝试为我的应用程序编写集成测试,但是每次它碰到getNameAsync()方法时,都会抛出一个null异常,因为ContextType.Domain为null。

我在线阅读并找到了使用自定义身份进行测试的方法,因此,现在User.Identity.Name返回我想要的任何内容,但是我找不到模拟或定义Custom ContextType.Domain或模拟PrincipalContext的方法...我以为我可以使用ClaimsPrincipal.FindFirstValue(ClaimType.GivenName)代替使用PrincipalContext,但它始终返回null。

这是我的集成测试:

public class BrowseControllerTest : IClassFixture<CustomApplicationFactory<Startup>>
    {
        protected readonly HttpClient _client;

        public BrowseControllerTest(CustomApplicationFactory<Startup> factory)
        {
            _client = factory.CreateClient();
        }

        [Theory]
        [InlineData(1)]
        [InlineData(2)]
        public async Task ReturnDomain(int value)
        {
            var response = await _client.GetAsync("/Browse/Domain/"+value);
            response.EnsureSuccessStatusCode();
        }
    }

我的CustomApplicationFactory,允许我使用测试数据库和用户身份:

public class CustomApplicationFactory<TStartup>
        : WebApplicationFactory<TStartup> where TStartup : class
    {
        protected override void ConfigureWebHost(IWebHostBuilder builder)
        {
            builder.ConfigureServices(services =>
            {
                // Remove the app's ApplicationDbContext registration.
                var descriptor = services.SingleOrDefault(
                    d => d.ServiceType ==
                        typeof(DbContextOptions<My_DBContext>));

                if (descriptor != null)
                {
                    services.Remove(descriptor);
                }

                // Add ApplicationDbContext using an in-memory database for testing.
                services.AddDbContext<BRG_DistributionContext>(options =>
                {
                    options.UseInMemoryDatabase("InMemoryDbForTesting");
                });

                services.AddAuthentication(o =>
               {
                   o.DefaultScheme = "TestScheme";
               }).AddCustomAuthentication("TestScheme", "My custom authentication scheme", o => { });

                // Build the service provider.
                var sp = services.BuildServiceProvider();

                using (var scope = sp.CreateScope())
                {
                    var scopedServices = scope.ServiceProvider;
                    var db = scopedServices.GetRequiredService<BRG_DistributionContext>();
                    var logger = scopedServices
                        .GetRequiredService<ILogger<CustomApplicationFactory<TStartup>>>();

                    // Ensure the database is created.
                    db.Database.EnsureCreated();

                    try
                    {
                        // Seed the database with test data.
                        Utilities.InitializeDbForTests(db);
                    }
                    catch (Exception ex)
                    {
                        logger.LogError(ex, "An error occurred seeding the " +
                            "database with test messages. Error: {Message}", ex.Message);
                    }
                }
            });
        }

所以我的问题是:如何模拟/定义自定义ContextType.Domain或PrincipalContext?如果不可能,如果FindFirstValue(ClaimTypes.GivenName)返回null,如何使用声明获取当前用户的名字和姓氏?

0 个答案:

没有答案