如何模拟MVC 5控制器的OWINContext

本文关键字:控制器 OWINContext MVC 何模拟 模拟 | 更新日期: 2023-09-27 17:58:20

我有一个BaseController,我的所有控制器都从它派生,它在ViewBag中设置一个值(用户的昵称)。我这样做是为了在布局中访问该值,而不必为每个控制器隐式地设置它(如果你只是建议一种更好的方法,请继续!)。

public class BaseController : Controller
{
    public BaseController()
    {
        InitialiseViewBag();
    }
    protected void InitialiseViewBag()
    {
        ApplicationUser user = System.Web.HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>().FindById(System.Web.HttpContext.Current.User.Identity.GetUserId());
        ViewBag.NickName = user?.NickName;
    }
}

然后,我派生出这个类,例如,在HomeController:中

public class HomeController : BaseController
{
    private readonly IRoundRepository _repository = null;
    public HomeController(IRoundRepository repository)
    {
        _repository = repository;
    }
    public ActionResult Index()
    {
        return View();
    }
}

我已经设置了我的控制器的另一个依赖项(存储库,在另一个视图中使用,此处未显示)来访问构造函数,并使用StructureMap进行DI,当我去掉BaseController中用于获取昵称的行时,这一切都很好。

问题是,当我使用OWIN上下文包含这一行以获得昵称时,我的测试失败了

System.InvalidOperationException:无owin。已找到环境项在上下文中。

这是我目前的测试:

[TestMethod]
public void HomeControllerSelectedIndexView()
{
    // Arrange
    HttpContext.Current = _context;
    var mockRoundRepo = new Mock<IRoundRepository>();
    HomeController controller = new HomeController(mockRoundRepo.Object);
    // Act
    ViewResult result = controller.Index() as ViewResult;
    // Assert
    Assert.IsNotNull(result);
}

我想我理解为什么它不起作用,但我不知道如何绕过它。

我应该如何嘲笑/注入/以其他方式设置这个基本控制器,以便它可以访问用户的身份,而不会在测试过程中崩溃?

注意:我对使用依赖注入还很陌生,所以如果这是明显的事情,或者我完全错了,或者遗漏了任何重要信息,我不会感到惊讶!

如何模拟MVC 5控制器的OWINContext

感谢Nkosi的建议,我使用声明解决了这个问题。

在我的ApplicationUser.GenerateUserIdentityAsync()方法中,我为他们的身份添加了声明:

userIdentity.AddClaim(new Claim("NickName", this.NickName));

我添加了一个助手扩展方法,用于访问Identity对象的NickName声明:

public static class IdentityExtensions
{
    public static string GetNickName(this IIdentity identity)
    {
        var claim = ((ClaimsIdentity)identity).FindFirst("NickName");
        // Test for null to avoid issues during local testing
        return (claim != null) ? claim.Value : string.Empty;
    }
}

现在,在我的视图(或控制器)中,我可以直接访问索赔,例如:

<span class="nickname">@User.Identity.GetNickName()</span>