我有一个具有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,如何使用声明获取当前用户的名字和姓氏?