需要帮助在需要 HttpContext.Current.User 的方法上编写单元测试
我正在尝试为我的 MVC3 项目编写一些单元测试(该项目的第一个测试),但我被难住了。基本上,我有一个 MemberQueries 类,我的 MemberController 使用它来处理所有逻辑。
我想开始在这个类上编写测试,并想从一个简单的例子开始。我在这个类中有一个名为 IsEditModeAvailable 的方法,它确定用户是否是“站点管理员”角色的成员,或者用户是否能够编辑自己的数据,但不能编辑其他人的数据。我通过将传入的 Id 值与 HttpContext User 属性进行比较来确定最后一个要求。
我遇到的问题是我不知道在创建 MemberQueries 对象时如何模拟或注入正确的参数到我的单元测试中。我正在使用NUnit、Moq 和Ninject,但我只是不确定如何编写代码。如果我的结构不正确,请告诉我,因为我对单元测试完全是菜鸟。
这是我的 MemberQueries 类中的代码示例:
public class MemberQueries : IMemberQueries
{
private readonly IRepository<Member> _memberRepository;
private readonly IMemberServices _memberServices;
private readonly IPrincipal _currentUser;
public MemberQueries(IUnitOfWork unitOfWork, IMemberServices memberServices, IPrincipal currentUser)
{
_memberRepository = unitOfWork.RepositoryFor<Member>();
_memberServices = memberServices;
_currentUser = currentUser;
}
public bool IsEditModeAvailable(int memberIdToEdit)
{
if (_currentUser.IsInRole("Site Administrator")) return true;
if (MemberIsLoggedInUser(memberIdToEdit)) return true;
return false;
}
public bool MemberIsLoggedInUser(int memberIdToEdit)
{
var loggedInUser = _memberServices.FindByEmail(_currentUser.Identity.Name);
if (loggedInUser != null && loggedInUser.Id == memberIdToEdit) return true;
return false;
}
}
这是我的 MemberServices 类中的示例(位于我的域项目中,由 MemberQueries 引用):
public class MemberServices : IMemberServices
{
private readonly IRepository<Member> _memberRepository;
public MemberServices(IUnitOfWork unitOfWork)
{
_memberRepository = unitOfWork.RepositoryFor<Member>();
}
public Member Find(int id)
{
return _memberRepository.FindById(id);
}
public Member FindByEmail(string email)
{
return _memberRepository.Find(m => m.Email == email).SingleOrDefault();
}
}
最后,这是我尝试编写的单元测试的存根:
[Test]
public void LoggedInUserCanEditTheirOwnInformation()
{
var unitOfWork = new UnitOfWork();
var currentUser = new Mock<IPrincipal>();
// I need to somehow tell Moq that the logged in user has a HttpContext.User.Name of "[email protected]"
var memberServices = new Mock<MemberServices>();
// I then need to tell Moq that it's FindByEmail("[email protected]") method should return a member with a UserId of 1
var memberQueries = new MemberQueries(unitOfWork, memberServices.Object, currentUser.Object);
// If the logged in user is "[email protected]" who has an Id of 1, then IsEditModeAvailable(1) should return true
Assert.IsTrue(memberQueries.IsEditModeAvailable(1));
}
I am trying to write some unit tests for my MVC3 project (the first tests for this project) and I am getting stumped. Basically, I have a MemberQueries class that is used by my MemberController to handle all the logic.
I want to start writing tests on this class and want to start with a simple example. I have a method in this class called IsEditModeAvailable which determines if the user is a member of the "Site Administrator" role or that the user is able to edit their own data, but no one elses. I determine the last requirement by comparing the passed in Id value to the HttpContext User property.
The problem that I'm running into is I don't know how to mock or inject the proper parameters into my unit tests when creating the MemberQueries object. I am using, NUnit, Moq and Ninject, but I'm just not sure how to write the code. If I'm just not structuring this properly, please let me know as I'm a complete noob to unit testing.
Here's a sample of the code from my MemberQueries class:
public class MemberQueries : IMemberQueries
{
private readonly IRepository<Member> _memberRepository;
private readonly IMemberServices _memberServices;
private readonly IPrincipal _currentUser;
public MemberQueries(IUnitOfWork unitOfWork, IMemberServices memberServices, IPrincipal currentUser)
{
_memberRepository = unitOfWork.RepositoryFor<Member>();
_memberServices = memberServices;
_currentUser = currentUser;
}
public bool IsEditModeAvailable(int memberIdToEdit)
{
if (_currentUser.IsInRole("Site Administrator")) return true;
if (MemberIsLoggedInUser(memberIdToEdit)) return true;
return false;
}
public bool MemberIsLoggedInUser(int memberIdToEdit)
{
var loggedInUser = _memberServices.FindByEmail(_currentUser.Identity.Name);
if (loggedInUser != null && loggedInUser.Id == memberIdToEdit) return true;
return false;
}
}
Here's a sample from my MemberServices class (which is in my domain project, referenced by MemberQueries):
public class MemberServices : IMemberServices
{
private readonly IRepository<Member> _memberRepository;
public MemberServices(IUnitOfWork unitOfWork)
{
_memberRepository = unitOfWork.RepositoryFor<Member>();
}
public Member Find(int id)
{
return _memberRepository.FindById(id);
}
public Member FindByEmail(string email)
{
return _memberRepository.Find(m => m.Email == email).SingleOrDefault();
}
}
Finally, here's the stub of the unit test I am trying to write:
[Test]
public void LoggedInUserCanEditTheirOwnInformation()
{
var unitOfWork = new UnitOfWork();
var currentUser = new Mock<IPrincipal>();
// I need to somehow tell Moq that the logged in user has a HttpContext.User.Name of "[email protected]"
var memberServices = new Mock<MemberServices>();
// I then need to tell Moq that it's FindByEmail("[email protected]") method should return a member with a UserId of 1
var memberQueries = new MemberQueries(unitOfWork, memberServices.Object, currentUser.Object);
// If the logged in user is "[email protected]" who has an Id of 1, then IsEditModeAvailable(1) should return true
Assert.IsTrue(memberQueries.IsEditModeAvailable(1));
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您似乎正在尝试测试
MemberQueries.IsEditModeAvailable
方法。这里有 2 个案例需要介绍。站点管理员
情况以及当前登录用户的 id 与作为参数传递的用户的 id 匹配的情况。由于MemberQueries
类纯粹依赖于接口,因此您可以模拟所有内容:实际上,您需要涵盖第三种情况:您当前登录的用户不是站点管理员,并且其 id 不是站点管理员t 与作为参数传递的匹配:
It looks like you are trying to test the
MemberQueries.IsEditModeAvailable
method. You have 2 cases to cover here. TheSite Administrators
case and the case where there's a currently logged user whose id matches the one passed as argument. And since theMemberQueries
class relies purely on interfaces you could mock everything:Actually there's a third case you need to cover: you have a currently logged in user, who is not a Site Administrator and whose id doesn't match the one passed as argument:
好消息是您将用户作为 IPrincipal 传递到需要它的代码中,而不是引用 HttpContext.Current.User。您需要做的就是设置模拟 IPrincipal,以便它返回该测试所需的值。
The good news is that you are passing the user as an IPrincipal into the code that needs it rather than referring to HttpContext.Current.User. All you should need to do is setup the mock IPrincipal so that it returns the vales you need for that test.