Модульный тест MVC4 и аутентификация Windows
Насколько я вижу, если мое приложение mvc4 не использует проверку подлинности Windows (и поэтому мои контроллеры не пытаются читать объекты User), когда я создаю свой экземпляр контроллера из TestMethod, объект User остается нулевым. Так что мои тесты не пройдены. Что я могу сделать, чтобы заставить их работать?
Дополнительная информация: Это мой тест:
[TestMethod]
public void Create()
{
var ctrl = new LanguageController();
var res = ctrl.Manage() as ViewResult;
Assert.IsNotNull(res);
Assert.AreEqual(res.ViewName, "Create");
}
А у моего LanguageController есть базовый класс:
public class LanguageController : MyController
{
У которого есть конструктор, внутри которого я пытаюсь обнаружить права пользователя с помощью внешнего диспетчера прав.
public class MyController : Controller
{
protected Rights rm;
public MyController()
{
this.rm = RightManager.Discover(User.Identity);
}
Здесь, в этом конструкторе, я вижу, что пользователь является нулевым.
1 ответ
Хорошо, у вас есть несколько проблем с вашим модульным тестом, и я рассмотрю их, объясняя, почему пользователь является нулевым.
Это просто потому, что вы не предоставили заглушенную версию экземпляра User (IPrincipal). Так что вам нужно найти способ внедрить это в ваш контроллер. Важно, чтобы вы вывели как можно больше зависимостей в свой контроллер, чтобы он не был чистым контроллером для работы, а также, что немаловажно, улучшал тестируемость.
Что бы я сделал, чтобы ввести зависимости, как показано ниже.
Ваше SUT (тестируемая система)
public class MyController : Controller
{
protected Rights rm;
public MyController(IPrincipal user, IRightManager rightManager)
{
this.rm = rightManager.Discover(user.Identity);
}
}
public class LanguageController : MyController
{
public LanguageController(IPrincipal user, IRightManager rightManager)
: base(user, rightManager)
{
}
public ActionResult Manage()
{
return View("Manage");
}
}
Это дает мне возможность ввести поддельного пользователя, а также поддельного правого менеджера.
Итак, как бы вы получили настоящий пользователь Right Manager при запуске приложения во время выполнения?
Вы можете внедрить зависимости в контроллер при создании контроллера.
Если вы не используете инфраструктуру внедрения зависимостей (в идеале, вы должны это делать), вы все равно можете вводить зависимости вручную. Например, создавая свойство в вашем контроллере и вставляя реальный экземпляр в контроллер, а во время модульного тестирования внедряйте поддельный экземпляр и т. Д. Я не буду вдаваться в подробности, так как немного отклоняюсь - но вы можете найти много SO вопросы / веб-ссылки в отношении этого аспекта.
Ваш юнит-тест Теперь у вас есть способ внедрить ваши зависимости, вы можете легко внедрить их из вашего юнит-теста. Вы можете либо использовать платформу Isolation (AKA и Mock Object Framework), либо вы можете внедрить их как в старом школьном стиле, то есть написанные от руки mocks / fakes/stubs. Я предлагаю использовать каркас изоляции. Создание ручных подделок, вводит ненужное дублирование кода и проблему обслуживания. Поскольку я не знаю, какой фреймворк вы предпочитаете, я создал несколько рукописных фальшивок / издевательств / заглушек.
public class FakeRightManager : IRightManager {
public Rights Discover(IIdentity identity) {
return new Rights();
}
}
public class MyFakeIdentity : IIdentity {
public string AuthenticationType {
get { throw new NotImplementedException(); }
}
public bool IsAuthenticated {
get { throw new NotImplementedException(); }
}
public string Name {
get { throw new NotImplementedException(); }
}
}
public class MyFakePrincipal : IPrincipal {
public IIdentity Identity {
get { return new MyFakeIdentity(); }
}
public bool IsInRole(string role) {
throw new NotImplementedException();
}
}
Вы юнит тест:
[TestMethod]
public void ManageAction_Execute_ReturnsViewNameManager()
{
var fakeUser = new MyFakePrincipal();
var fakeRightManager = new FakeRightManager();
var ctrl = new LanguageController(fakeUser, fakeRightManager);
var res = ctrl.Manage() as ViewResult;
Assert.AreEqual<string>(res.ViewName, "Manage");
}
В своем тесте вы проверяете Assert.IsNotNull(res); это не обязательно, как если бы res равнялся нулю, ваш второй assert в любом случае потерпит неудачу.
Также всегда дайте очень наглядное и точное название модульного теста. Подумайте, что именно вы тестируете. Это улучшает тест читаемости и ремонтопригодности.