ASP / NET MVC: тестовые контроллеры с сессиями? Дразнящий? - PullRequest
43 голосов
/ 07 октября 2008

Я прочитал некоторые ответы здесь: тестирование представлений и контроллеров, а также макетирование, но я все еще не могу понять, как протестировать контроллер ASP.NET MVC, который читает и устанавливает значения сеанса (или любой другой контекст, основанный переменные.) Как мне предоставить (Session) контекст для моих методов тестирования? Это насмешливый ответ? У кого-нибудь есть примеры? По сути, я хотел бы подделать сеанс до того, как я вызову метод контроллера и заставлю контроллер использовать этот сеанс. Есть идеи?

Ответы [ 7 ]

44 голосов
/ 26 октября 2008

Ознакомьтесь с постом Стивена Вальтера о фальсификации контекста контроллера:

ASP.NET MVC Совет № 12 - Подделка контекста контроллера

[TestMethod]
public void TestSessionState()
{
    // Create controller
    var controller = new HomeController();


    // Create fake Controller Context
    var sessionItems = new SessionStateItemCollection();
    sessionItems["item1"] = "wow!";
    controller.ControllerContext = new FakeControllerContext(controller, sessionItems);
    var result = controller.TestSession() as ViewResult;


    // Assert
    Assert.AreEqual("wow!", result.ViewData["item1"]);

    // Assert
    Assert.AreEqual("cool!", controller.HttpContext.Session["item2"]);
}
13 голосов
/ 07 октября 2008

Платформа ASP.NET MVC не очень удобна для моделирования (или, скорее, требует слишком большой настройки для правильного моделирования и вызывает слишком много трений при тестировании, IMHO) из-за использования абстрактных базовых классов вместо интерфейсов. Нам повезло с написанием абстракций для хранилища на основе запросов и сеансов. Мы сохраняем эти абстракции очень легкими, и тогда наши контроллеры зависят от этих абстракций для хранения по запросу или по сеансу.

Например, вот как мы справляемся с аутентификацией форм. У нас есть ISecurityContext:

public interface ISecurityContext
{
    bool IsAuthenticated { get; }
    IIdentity CurrentIdentity { get; }
    IPrincipal CurrentUser { get; set; }
}

С конкретной реализацией, такой как:

public class SecurityContext : ISecurityContext
{
    private readonly HttpContext _context;

    public SecurityContext()
    {
        _context = HttpContext.Current;
    }

    public bool IsAuthenticated
    {
        get { return _context.Request.IsAuthenticated; }
    }

    public IIdentity CurrentIdentity
    {
        get { return _context.User.Identity; }
    }

    public IPrincipal CurrentUser
    {
        get { return _context.User; }
        set { _context.User = value; }
    }
}
10 голосов
/ 17 февраля 2009

С MVC RC 1 ControllerContext оборачивает HttpContext и представляет его как свойство. Это делает издевательство намного проще. Чтобы смоделировать переменную сеанса с Moq, сделайте следующее:

var controller = new HomeController();
var context = MockRepository.GenerateStub<ControllerContext>();
context.Expect(x => x.HttpContext.Session["MyKey"]).Return("MyValue");
controller.ControllerContext = context;

См. сообщение Скотта Гу для более подробной информации.

5 голосов
/ 07 октября 2008

Я нашел насмешку довольно легким. Вот пример макета httpContextbase (который содержит объекты запроса, сеанса и ответа) с использованием moq.

[TestMethod]
        public void HowTo_CheckSession_With_TennisApp() {
            var request = new Mock<HttpRequestBase>();
            request.Expect(r => r.HttpMethod).Returns("GET");     

            var httpContext = new Mock<HttpContextBase>();
            var session = new Mock<HttpSessionStateBase>();

            httpContext.Expect(c => c.Request).Returns(request.Object);
            httpContext.Expect(c => c.Session).Returns(session.Object);

            session.Expect(c => c.Add("test", "something here"));            

            var playerController = new NewPlayerSignupController();
            memberController.ControllerContext = new ControllerContext(new RequestContext(httpContext.Object, new RouteData()), playerController);          

            session.VerifyAll(); // function is trying to add the desired item to the session in the constructor
            //TODO: Add Assertions   
        }

Надеюсь, это поможет.

2 голосов
/ 25 марта 2012

Я использовал следующее решение - создание контроллера, от которого наследуются все остальные мои контроллеры.

public class TestableController : Controller
{

    public new HttpSessionStateBase Session
    {
        get
        {
            if (session == null)
            {
                session = base.Session ?? new CustomSession();
            }
            return session;
        }
    }
    private HttpSessionStateBase session;

    public class CustomSession : HttpSessionStateBase
    {

        private readonly Dictionary<string, object> dictionary; 

        public CustomSession()
        {
            dictionary = new Dictionary<string, object>();
        }

        public override object this[string name]
        {
            get
            {
                if (dictionary.ContainsKey(name))
                {
                    return dictionary[name];
                } else
                {
                    return null;
                }
            }
            set
            {
                if (!dictionary.ContainsKey(name))
                {
                    dictionary.Add(name, value);
                }
                else
                {
                    dictionary[name] = value;
                }
            }
        }

        //TODO: implement other methods here as needed to forefil the needs of the Session object. the above implementation was fine for my needs.

    }

}

Затем используйте код следующим образом:

public class MyController : TestableController { }
2 голосов
/ 07 октября 2008

Скотт Хансельман имеет пост о том, как создать файл для загрузки quickapp с MVC, и обсуждает насмешки, а также посвящен теме "Как издеваться над вещами, которые не дружелюбны".

0 голосов
/ 24 апреля 2009

Поскольку HttpContext является статическим, я использую Typemock Isolator, чтобы смоделировать его, Typemock также имеет специальную надстройку, созданную для ASP.NET модульного тестирования под названием Ivonna .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...