如何为MVC 5控制器模拟OWINContext

时间:2016-07-22 06:45:45

标签: c# asp.net-mvc unit-testing structuremap

我有一个我的控制器派生自的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.Environment项   在上下文中。

这是我现在的测试:

[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);
}

我想我明白为什么它不起作用,但我无法弄清楚如何绕过它。

我应该如何模拟/注入/设置此基本控制器,以便它可以访问用户的身份而不会在我的测试过程中崩溃?

注意:我对使用依赖注入很新,所以如果它显然是某些东西,或者我认为这完全错了,或者遗漏任何重要信息,我不会感到惊讶!

1 个答案:

答案 0 :(得分:1)

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

在我的ApplicationUser.GenerateUserIdentityAsync()方法中,我将声明添加到其身份中:

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

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

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>