我有一个我的控制器派生自的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);
}
我想我明白为什么它不起作用,但我无法弄清楚如何绕过它。
我应该如何模拟/注入/设置此基本控制器,以便它可以访问用户的身份而不会在我的测试过程中崩溃?
注意:我对使用依赖注入很新,所以如果它显然是某些东西,或者我认为这完全错了,或者遗漏任何重要信息,我不会感到惊讶!
答案 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>