【发布时间】:2014-06-10 01:01:33
【问题描述】:
编写需要通过我的 CustomMembershipProvider 访问数据库的单元测试。
edit-
public class CustomMembershipProvider : MembershipProvider
{
public override bool ValidateUser(string username, string password)
{
using (var usersContext = new UsersContext())
{
var requiredUser = usersContext.GetUser(username, password);
var userApproved = usersContext.GetUserMem(username);
if (userApproved == null) return false;
return (requiredUser != null && userApproved.IsApproved != false);
}
}
}
[TestFixture]
public class AccountControllerTest
{
[Test]
public void ShouldNotAcceptInvalidUser()
{
// OPTION1
Mock<IMembershipService> membership = new Mock<IMembershipService>();
//OPTION2
// Mock<AccountMembershipService> membership = new Mock<AccountMembershipService>();
membership.Setup(m => m.ValidateUser(It.IsAny<string>(), It.IsAny<string>()))
.Returns(false);
var logonModel = new LoginModel() { EmailorUserName = "connorgerv", Password = "pasdsword1" };
var controller = new AccountController(membership.Object);
// Act
var result = controller.Login(logonModel,"Index") as RedirectResult;
// Assert
Assert.That(result.Url, Is.EqualTo("Index"));
Assert.False(controller.ModelState.IsValid);
Assert.That(controller.ModelState[""],
Is.EqualTo("The user name or password provided is incorrect."));
}
[Test]
public void ExampleForMockingAccountMembershipService()
{
var validUserName = "connorgerv";
var validPassword = "passwordd1";
var stubService = new Mock<CustomMembershipProvider>();
bool val = false;
stubService.Setup(x => x.ValidateUser(validUserName, validPassword)).Returns(true);
Assert.IsTrue(stubService.Object.ValidateUser(validUserName, validPassword));
}
}
public class AccountController : Controller
{
public IMembershipService MembershipService { get; set; }
public AccountController(IMembershipService service){
MembershipService=service;
}
protected override void Initialize(RequestContext requestContext)
{
if (MembershipService == null) { MembershipService = new AccountMembershipService(); }
base.Initialize(requestContext);
}
public ActionResult Index()
{
return RedirectToAction("Profile");
}
public ActionResult Login()
{
if (User.Identity.IsAuthenticated)
{
//redirect to some other page
return RedirectToAction("Index", "Home");
}
return View();
}
//
// POST: /Account/Login
[HttpPost]
public ActionResult Login(LoginModel model, string ReturnUrl)
{
if (ModelState.IsValid)
{
if (MembershipService.ValidateUser(model.EmailorUserName, model.Password))
{
SetupFormsAuthTicket(model.EmailorUserName, model.RememberMe);
if (Url.IsLocalUrl(ReturnUrl) && ReturnUrl.Length > 1 && ReturnUrl.StartsWith("/")
&& !ReturnUrl.StartsWith("//") && !ReturnUrl.StartsWith("/\\"))
{
return Redirect(ReturnUrl);
}
return RedirectToAction("Index", "Home");
}
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
// If we got this far, something failed, redisplay form
return View(model);
}
}
public class AccountMembershipService : IMembershipService
{
private readonly MembershipProvider _provider;
public AccountMembershipService()
: this(null)
{
}
public AccountMembershipService(MembershipProvider provider)
{
_provider = provider ?? Membership.Provider;
}
public virtual bool ValidateUser(string userName, string password)
{
if (String.IsNullOrEmpty(userName)) throw new ArgumentException("Value cannot be null or empty.", "userName");
if (String.IsNullOrEmpty(password)) throw new ArgumentException("Value cannot be null or empty.", "password");
return _provider.ValidateUser(userName, password);
}
}
Membership in web.config of main application
<membership defaultProvider="CustomMembershipProvider">
<providers>
<clear />
<add name="CustomMembershipProvider" type="QUBBasketballMVC.Infrastructure.CustomMembershipProvider" connectionStringName="UsersContext" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" applicationName="/" />
</providers>
</membership>
public class CustomMembershipProvider : MembershipProvider
{
public override bool ValidateUser(string username, string password)
{
using (var usersContext = new UsersContext())
{
var requiredUser = usersContext.GetUser(username, password);
var userApproved = usersContext.GetUserMem(username);
if (userApproved == null) return false;
return (requiredUser != null && userApproved.IsApproved != false);
}
}
}
当我在未注释 Option1 的情况下运行 ShouldNotAcceptInvalidUser() 时会发生什么我可以看到 MembershipService 是 AccountController 中的 Mock<IMembershipService> 但它从未在登录操作中进入 MembershipService.ValidateUser。
当我在未注释选项 2 的情况下运行时,会发生同样的事情,除了 MembershipService 在 accountcontroller 中是 Mock<AccountMembershipService> 并且它使用 null 参数访问 AccountMembership 构造函数,而后者又将 SqlMembershipProvider 设置为 Membership.Provider 是 System.Web.Security.SqlMembershipProvider
另外,ExampleForMockingAccountMembershipService() 在CustomMembershipProvider 中似乎根本没有使用ValidateUser 方法并且总是返回true。
希望这足以看出我哪里出错了! :/
【问题讨论】:
-
您提供的链接中的信息如何不起作用? (例如,
_provider是否仍显示为SqlMembershipProvider?)这是在为测试项目添加配置后的 app.config 吗? -
对不起,我从来没有看到你的回复,是的,提供者仍然显示为 SqlMembershipProvider!我已经尝试将配置添加到 app.config 并且没有运气!这段代码应该工作吗?
[Test] public void ExampleForMockingAccountMembershipService() { var validUserName = "connorgerv"; var validPassword = "passwordd1"; var stubService = new Mock<CustomMembershipProvider>(); stubService.Setup(x => x.ValidateUser(validUserName, validPassword)).Returns(true); Assert.IsTrue(stubService.Object.ValidateUser(validUserName, validPassword)); } -
我不是想问一个愚蠢的问题,但是您是否对 test 项目中的
app.config进行了配置更改? (也就是说,不是定义了AccountMembershipService的项目,而是定义了你的测试的项目。) 至于你的代码是否应该工作,没有看到CustomMembershipProvider的代码很难说。话虽如此,如果您尝试测试CustomMembershipProvider,那么您不应该嘲笑它。 -
Lilshieste,我已经用我的代码的 sn-p 更新了帖子。我确实将成员身份配置文件添加到了测试项目的 app.config 中,但是当我在某处读到这没有必要时将其删除?
-
感谢您发布代码。我很困惑——我们可能在谈论两件不同的事情。您在测试中没有看到
SqlMembershipProvider(ExampleForMockingAccountMembershipService),对吗? (在您的 OP 中,您表示您在AccountMembershipService._provider中看到了它,但AccountMembershipService没有出现在您在上面评论中发布的测试代码中。)
标签: asp.net-mvc unit-testing app-config custom-membershipprovider