Как настроить IPrincipal для макета? - PullRequest
10 голосов
/ 22 августа 2009

Я хочу макет IPrincipal, поэтому я сделал это

public Mock<IPrincipal> Principal { get; set; }

в моей настройке моей монахини

 Principal = new Mock<IPrincipal>();

Так что это должно быть все, что мне нужно в моем модульном тесте nunit, но как насчет моего файла контроллера?

Например, как мне его настроить?

Например, у меня есть членство. Поставщик

Так что я сделал в конструкторе контроллера, который я сделал

Provider = Membership.Provider;

Итак, в моем контроллере я просто использовал Provider. (Все, что мне нужно).

Я не уверен, как настроить «Принципал» таким же образом.

1 Ответ

20 голосов
/ 22 августа 2009

Вы говорите о ASP.NET MVC? Я так думаю.

Вы должны создать экземпляр контроллера и установить его RequestContext. Вы насмехаетесь над HttpContext RequestContext, а внутри этого HttpContext вы насмехаетесь над его свойством User и устанавливаете его в свой поддельный IPrincipal:

var principal = new Moq.Mock<IPrincipal>();
// ... mock IPrincipal as you wish

var httpContext = new Moq.Mock<HttpContextBase>();
httpContext.Setup(x => x.User).Returns(principal.Object);
// ... mock other httpContext's properties, methods, as needed

var reqContext = new RequestContext(httpContext.Object, new RouteData());

// now create the controller:
var controller = new MyController();
controller.ControllerContext =
    new ControllerContext(reqContext, controller);

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

EDIT:

Кстати, свойство User класса Controller происходит из объекта HttpContext, как вы можете видеть здесь (это метод получения свойства User, полученный из Reflector - вы также можете скачать исходный код ASP.NET MVC). ):

public IPrincipal User
{
    get
    {
        if (this.HttpContext != null)
        {
            return this.HttpContext.User;
        }
        return null;
    }
}

Если вы сейчас проверите свойство HttpContext, вы увидите:

public HttpContextBase HttpContext
{
    get
    {
        if (base.ControllerContext != null)
        {
            return base.ControllerContext.HttpContext;
        }
        return null;
    }
}

Итак, все до сих пор было «только для чтения». И нам нужен способ «внедрить» насмешливого «пользователя». Итак, мы проверяем, что на самом деле мы можем внедрить объект ControllerContext в контроллер через свойство. Мы проверяем, как он получает свой объект "HttpContext", чтобы узнать, как правильно его смоделировать:

public virtual HttpContextBase HttpContext
{
    get
    {
        if (this._httpContext == null)
        {
            this._httpContext = (this._requestContext != null) ? this._requestContext.HttpContext : new EmptyHttpContext();
        }
        return this._httpContext;
    }
    set
    {
        this._httpContext = value;
    }
}

Итак, здесь мы видим, что объект ControllerContext получает свой HttpContext от объекта RequestContext. Так что это может объяснить, что я сделал выше:

  1. Подделайте IPrincipal с данными, которые вы хотите,
  2. Создайте макет HttpContext и передайте его IPrincipal,
  3. Создайте макет RequestContext и передайте его HttpContext,
  4. Создайте экземпляр вашего контроллера и присвойте его свойству ControllerContext измененный объект RequestContext.

После всего этого волшебства контроллер не будет знать, что вы вызываете его, без фактического установления соединения через веб-сервер.

Таким образом, вы можете продолжать использовать свойство «Пользователь» внутри контроллера, как обычно, без изменений.

...