Как настроить IPrincipal для макета?

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

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

в моей настройке моего nunit

 Principal = new Mock<IPrincipal>();

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

Как мне настроить его?

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

Итак, что я сделал в моем конструкторе контроллера, я сделал

Provider = Membership.Provider;

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

Я не уверен, как настроить основную вещь таким же образом.

Ответ 1

Вы говорите об 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 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:

FYI, свойство User в классе Controller происходит из объекта HttpContext, как вы можете видеть здесь (это метод getter для свойства 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. Это может объяснить, что я сделал выше:

  • Откажитесь от IPrincipal с данными, которые вы хотите,
  • Откажитесь от HttpContext и передайте его с помощью IPrincipal,
  • Выделите RequestContext и передайте его с помощью HttpContext,
  • Создайте экземпляр вашего контроллера и установите его свойство ControllerContext для издевающегося объекта RequestContext.

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

Итак, вы можете продолжать использовать свое свойство "Пользователь" внутри вашего контроллера, как обычно, никаких изменений не должно быть сделано.