2013-09-21 2 views
1

Как провести тестирование контроллера, использующего Simple Memberhip?Единичный тест поставщика простого членства?

Контроллер принимает объект MyViewModel в качестве входа & вставляет его в БД. По завершении операции пользователь перенаправляется на Личный кабинет.

Контроллер имеет WebSecurity как зависимость. Поэтому при модульном тестировании я получаю исключение параметра null для HttpContext в следующей строке

userLakshya.UserId = WebSecurity.HasUserId? WebSecurity.CurrentUserId : -1;

Как передать параметр HttpContext контроллеру?

Код листинг:

[HttpPost] 
    public ActionResult Create(MyViewModel myVM) 
    { 
     MyModel myModel = myVM.Model; 
     if (ModelState.IsValid) 
     { 
      userLakshya.UserId = WebSecurity.HasUserId ? WebSecurity.CurrentUserId : -1; 
      db.MyModels.Add(myModel); 
      db.SaveChanges(); 
      return RedirectToAction("Dashboard"); 
     } 
     return View(myVM); 
    } 

    [TestMethod] 
    public void TestLoginAndRedirectionToDashboard() 
    { 
     MyController cntlr = new MyController(); 
     var ret = ulCntlr.Create(new MyViewModel(){ 
      //Initialize few properties to test 
     }); 
     /* 
     * Controller throws parameter null exception for HttpContext 
     * => Issue: Should I pass this? since the controller uses WebSecurity inside 
     * */ 
     ViewResult vResult = ret as ViewResult; 
     if (vResult != null) 
     { 
      Assert.IsInstanceOfType(vResult.Model, typeof(UserLakshya)); 
      UserLakshya model = vResult.Model as UserLakshya; 

      if (model != null) 
      { 
       //Assert few properties from the return type. 
      } 
     } 
    } 

ответ

1

Проблема у вас есть то, что ваш метод Create является нарушая Dependency Inversion Principle то ваш метод должны «Положитесь на абстракциях не зависит от конкрементов.».

Вы должны реорганизовать свой код, чтобы вместо использования класса WebSecurity вместо этого использовать абстракцию, например. вы можете создать интерфейс ISecurity. Ваша бетон версия ISecurity (например, Security) может затем содержать ссылку на WebSecurity и, следовательно, удалить прямую зависимость.

(Вы уже сделали это для вашей зависимости базы данных (т.е. ваш член дб), вам просто нужно сделать, это для аспекта безопасности вашего кода.)

например

public Interface ISecurity 
{ 
int GetUserId(); 
} 

Тогда вместо:

userLakshya.UserId = WebSecurity.HasUserId ? WebSecurity.CurrentUserId : -1; 

вы можете использовать:

userLakshya.UserId = security.GetUserId(); 

Затем, чтобы проверить "Создать" контроллер можно издеваться поведение ISecurity (на самом деле я бы тоже рекомендовать насмехаться над поведением вашего объекта «db»), используя насмешливую структуру (например, Moq). Примером насмешливый с MOq код:

var mock = new Mock<ISecurity>(); 
mock.Setup(security=> security.GetUserId()).Returns("ATestUser"); 
+0

1. 'WebSecurity' не реализует любой интерфейс (это статический класс) 2. В моем коде,' Create' является метод действия, следовательно, вызывается со стороны клиента. Возможно ли передать дополнительный параметр, например 'WebSecurity' или' ISecurity' – Abhijeet

+0

. Я использую конструктор по умолчанию для создания экземпляра пользовательского класса, чтобы хранить 'WebSecurity.HasUserId' или' WebSecurity.CurrentUserId'. Я применяю атрибут фильтра Authorize для действия. Я думаю, что конструктор будет вызываться сначала перед «Авторизовать». В этом случае 'WebSecurity' будет null. Я прав? – Abhijeet

+0

@autrevo Я обновил свой ответ. Надеюсь, что теперь он станет более ясным? –

Смежные вопросы