У меня есть модульный тест для проверки моего метода AccountController.LogIn. Результат перенаправления возвращается, чтобы указать на успех, в противном случае возвращается результат просмотра.
Тест всегда терпит неудачу, поскольку типом возвращаемого значения всегда является 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);
}
Когда я запускаю тест, он не работает в методе входа в My 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 не запускается во время модульного тестирования? и поэтому мой пользовательский провайдер не вводится, следовательно, сбой?
ОБНОВЛЕНИЕ Я издевался над своим классом 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, которому можно было бы назначить поставщика, и я не ввожу его в конструктор.