我有一个单元测试来检查我的AccountController.LogIn方法。返回重定向结果以指示成功,否则返回viewresult。单元测试自定义MembershipProvider.ValidateUser,使用Global.asax中的代码
测试总是失败,因为返回类型始终是viewresult,即使测试应该返回成功,因为凭据是有效的,但我无法确定问题出在哪里。 我TestMethod的: CustomerRepositoryTest.cs
[TestMethod]
public void Can_Login_With_Valid_Credentials()
{
// Arrange
Mock<IAddressRepository> mockAddressRepository = new Mock<IAddressRepository>();
Mock<ICustomerRepository> mockCustomerRepository = new Mock<ICustomerRepository>();
Mock<IOrderRepository> mockOrderRepository = new Mock<IOrderRepository>();
LoginViewModel model = new LoginViewModel
{
Email = "[email protected]",
Password = "password"
};
AccountController target = new AccountController(mockCustomerRepository.Object, mockAddressRepository.Object, mockOrderRepository.Object);
// Act
ActionResult result = target.LogIn(model);
// Assert
Assert.IsInstanceOfType(result, typeof(RedirectResult));
Assert.AreEqual("", ((RedirectResult)result).Url);
}
当我运行测试,它在我的AccountController登录方法失败,当我打电话的ValidateUser AccountController.cs
if (Membership.ValidateUser(LoginModel.Email, LoginModel.Password))
{
...
return RedirectToRoute(new
{
controller = "Account",
action = "Details"
});
}
else
{
return View();
}
我定制的MembershipProvider ValidateUser看起来像这样:
个AccountMembershipProvider.cs
public class AccountMembershipProvider : MembershipProvider
{
[Inject]
public ICustomerRepository repository { get; set; }
public override bool ValidateUser(string username, string password)
{
var cust = repository.GetAllCustomers().SingleOrDefault..
当我运行应用程序,通常即不是测试,登录工作正常。在应用我注入CustomerRepository到自定义成员资格提供在的Global.asax:
public class MvcApplication : System.Web.HttpApplication
{
private IKernel _kernel = new StandardKernel(new MyNinjectModules());
internal class MyNinjectModules : NinjectModule
{
public override void Load()
{
Bind<ICustomerRepository>().To<CustomerRepository>();
}
}
protected void Application_Start()
{
_kernel.Inject(Membership.Provider);
...
难道在Global.asax代码不同时,单元测试运行的情况下?所以我的自定义提供程序没有被注入,因此失败?
UPDATE 我嘲笑我的Provider类,并将模拟的CustomerRepository对象传递给它。
Mock<AccountMembershipProvider> provider = new Mock<AccountMembershipProvider>();
provider.Object.repository = mockCustomerRepository.Object;
然后我创建了一个针对设置方法我想测试:
mockCustomerRepository.Setup(m => m.IsValidLogin("[email protected]", "password")).Returns(true);
但不幸的是,我仍然得到一个失败每次。为了回答关于我是否需要一个真正的或模拟的对象进行测试的问题 - 我并不挑剔,我只是想让它在这一刻起作用!
更新2
我做了这些变化,虽然它仍然失败,这也让我确定具体的问题。在调试测试,我发现,当我打电话覆盖
Membership.ValidateUser(LoginModel.Email, LoginModel.Password)
的Membership.Provider是类型的SqlMembershipProvider的(这大概是默认的类型),因此验证失败。
如果我投的供应商到我的自定义提供...
((AccountMembershipProvider)Membership.Provider).ValidateUser(LoginModel.Email, LoginModel.Password)
我运行测试时得到一个InvalidCastException。所以看起来我的模拟AccountMembershipProvider没有被用于测试,而是使用了默认的提供者。
我想你已经在注释中指出这一点:
// set your mock provider in your AccountController
但是我不知道你的意思究竟是什么 - 我没有在我的AccountController一个属性来指定供应商,并我没有注入到构造函数中。
为了让您知道,我在一天的早些时候通过编辑添加了更多信息。不要犹豫,要求澄清或更具体的信息。 – Gilles 2012-02-02 00:24:12
@Gilles - 我实施了你的建议(见更新)。他们为我澄清了很多,但每次都不幸失败!我是否需要为Provider和Repository类定义设置方法? – markpsmith 2012-02-02 11:27:56
我用一个例子更新我的帖子..基本上,如果你的提供者被嘲笑,没有必要为它的依赖创建模拟,因为模拟对象不会调用它们。 – Gilles 2012-02-02 13:41:20