【问题标题】:Mocking User ClaimsPrincipal for Razor Pages Unit Test模拟 Razor 页面单元测试的用户 ClaimsPrincipal
【发布时间】:2018-11-26 12:08:55
【问题描述】:

我有一个关于为结合 MVVM 的 Razor 页面编写单元测试的问题。我想测试 Razor 的 OnPostAsync() 方法,但是此方法将调用另外两个需要 ClaimsPrincipal 用户的方法。但是,我不能在我的测试中将User 作为这些方法的参数。

我目前的测试方法:

[Test]
public void MakeBookingTest()
{            
    //Arrange
    var optionsbuilder = new DbContextOptionsBuilder<ApplicationDbContext>();
    optionsbuilder.UseInMemoryDatabase(databaseName: "TeacherDB");
    var _dbContext = new ApplicationDbContext(optionsbuilder.Options);

    JsonResult json = new JsonResult(true);
    _dbContext.ImportOption.Add(new ImportOption { Id = 1, isUnique = 1, Option = "Teacher" });
    _dbContext.SaveChanges();

    var mockedUserManager = GetMockUserManager();           

    var mockedCalendar = new Mock<ICalendarService>();

    Booking booking = new Booking {
        EventId = "2",
        ClassroomId = 3,
        BeginTime = DateTime.Now,
        EndTime = DateTime.Now,
        Description = "fjdkafjal",
        Summary = "Test01" };

    mockedCalendar.Setup(x => x.CreateEvent(booking, "2", "0863629@hr.nl", false)).Returns("111");

    var mockedRoleManager = GetMockRoleManager();

    var model = new MakeBookingModel(_dbContext, mockedUserManager.Object, mockedCalendar.Object, mockedRoleManager.Object);
    //var controllerContext = new Mock<ControllerContext>();

    var result = model.OnPostAsync();                        
}

我要测试的方法:

[ValidateAntiForgeryToken]
public async Task<IActionResult> OnPostAsync()
{
    CurrentRole = await _validation.GetCurrentRole(User);
    CurrentUser = await _userManager.GetUserAsync(User);

 //(rest of the code...)

_validation.GetCurrentRole方法:

public async Task<string> GetCurrentRole(ClaimsPrincipal User)
{
    ApplicationUser currentUser = await _userManager.GetUserAsync(User);            
    Task<IList<string>> rolesUser = _userManager.GetRolesAsync(currentUser);
    return rolesUser.Result.First();
}

我似乎无法使OnPostAsync/GetCurrentRole 中的User 不为null

如何将User 分配给这些方法?

【问题讨论】:

  • User 上的 User 属性是只读的吗?
  • 继承自PageModel,貌似是public的
  • 您需要通过作为 PageContext 一部分的模拟 http 上下文来设置用户。
  • @Nkosi 感谢您的快速回复,我现在正在查看。我之前尝试过模拟一个 httpcontext,但它似乎不起作用,但我会再试一次。

标签: c# unit-testing asp.net-core razor-pages


【解决方案1】:

通过 HTTP 上下文设置User,该上下文是PageModelPageContext 的一部分

// Arrange

//...code removed for brevity

//Create test user
var displayName = "User name";
var identity = new GenericIdentity(displayName);
var principle = new ClaimsPrincipal(identity);
// use default context with user
var httpContext = new DefaultHttpContext() {
    User = principle
}
//need these as well for the page context
var modelState = new ModelStateDictionary();
var actionContext = new ActionContext(httpContext, new RouteData(), new PageActionDescriptor(), modelState);
var modelMetadataProvider = new EmptyModelMetadataProvider();
var viewData = new ViewDataDictionary(modelMetadataProvider, modelState);
// need page context for the page model
var pageContext = new PageContext(actionContext) {
    ViewData = viewData
};
//create model with necessary dependencies
var model = new MakeBookingModel(_dbContext, mockedUserManager.Object, mockedCalendar.Object, mockedRoleManager.Object) {
    PageContext = pageContext
};

//Act

//...

参考Razor Pages unit tests in ASP.NET Core

您正在混合使用异步调用和阻塞调用,例如 .Result,这会导致 GetCurrentRole 出现死锁。

一直重构为异步

public async Task<string> GetCurrentRole(ClaimsPrincipal User) {
    ApplicationUser currentUser = await _userManager.GetUserAsync(User);            
    var rolesUser = await _userManager.GetRolesAsync(currentUser);
    return rolesUser.FirstOrDefault();
}

【讨论】:

  • 这似乎有效!太感谢了!我现在唯一的问题是测试本身没有进入第二种方法(CurrentRole = ...GetUserAsync(),但似乎在第一部分之后停止。但这将有很大帮助。跨度>
  • @RaspberryInIT 你遇到了死锁。检查答案中的更新。
猜你喜欢
  • 2018-10-06
  • 1970-01-01
  • 1970-01-01
  • 2019-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多