модульное тестирование dotnetopenauth ctp - PullRequest
2 голосов
/ 18 января 2012

Я реализую oauth-провайдера, используя CTP-библиотеку DotNetOpenAuth. Итак, я создал приложение mvc3, в котором есть контроллер OAuth с тремя методами для авторизации сторонних приложений. Контроллер имеет IOAuthService, который инкапсулирует всю логику, которую должна выполнять библиотека для выполнения определенных задач, однако методы службы возвращают объекты DotNetOpenOAuth, защищенные конструкторами которых они являются.

Я хотел бы проверить поведение методов в моем OAuthController, для этого я пытаюсь смоделировать свои методы обслуживания, но я не смог этого сделать. Я должен сообщить библиотеке moq, какой тип объекта я ожидаю, что метод сервиса вернется, и, поскольку я не могу получить доступ к конструкторам этих объектов, я не могу выполнить тест по методу контроллера.

Контроллер:

public class OAuthController : Controller
{
    private readonly IOAuthService _oAuthService;

    public OAuthController(IOAuthService oAuthService)
    {
        _oAuthService = oAuthService;
    }

    [Authorize, AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]
    public ActionResult Authorize()
    {
        ClientApplication requestingClient;
        var request = _oAuthService.ReadAuthorizationRequest();
        if (request == null)
        {
            throw new HttpException((int)HttpStatusCode.BadRequest, "Missing authorization request.");
        }

        var response = _oAuthService.RequestClientAuthorization(GetIdentity().Name, out requestingClient, request);
        if (response != null)
        {
            return response.AsActionResult();
        }

        var model = new AuthorizeClientApplicationViewModel
        {
            ClientApplication = requestingClient.Name,
            Scope = request.Scope,
            AuthorizationRequest = request,
        };

        return View(model);
    }

    public virtual IIdentity GetIdentity()
    {
        return User.Identity;
    }
}

Я хочу проверить, что всякий раз, когда стороннее приложение не имеет авторизации, пользователю будет отображаться представление, запрашивающее его разрешение на авторизацию приложения. Для этого мне нужно издеваться:

  • _oAuthService.RequestClientAuthorization

Настройка моего метода тестирования будет выглядеть следующим образом:

var oAuthService = new Mock<IOAuthService>();
oAuthService.Setup(a => a.RequestClientAuthorization(userName, out client, pendingRequest)).Returns(new OutgoingWebResponse()); // DotNetOpenAuth doesn't allow me to do the **new OutgoingWebResponse**

PD: Для этого вопроса я написал только один из методов контроллера, но есть 3, и у них есть похожие сценарии.

Ответы [ 2 ]

1 голос
/ 18 января 2012

Одна из возможностей - написать оболочку (так же, как ASP.NET MVC абстрагирует все вещи, относящиеся к контексту HTTP):

public abstract class OutgoingWebResponseWrapperBase
{
    protected OutgoingWebResponseWrapperBase() { }

    public abstract ActionResult AsActionResult();
}

и затем иметь наивную реализацию:

public class OutgoingWebResponseWrapper: OutgoingWebResponseWrapperBase
{
    private readonly OutgoingWebResponse _response;
    public OutgoingWebResponseWrapper(OutgoingWebResponse response)
    {
        _response = response;
    }

    public override ActionResult AsActionResult()
    {
        return _response.AsActionResult();
    }
}

Теперь измените метод IOAuthService.RequestClientAuthorization, чтобы он возвращал OutgoingWebResponseWrapperBase вместо OutgoingWebResponse.

Просто так:

public interface IOAuthService
{
    ...
    OutgoingWebResponseWrapperBase RequestClientAuthorization(...);
}

Очевидно, ваш код контроллера останется прежним. Просто теперь вы можете смоделировать тип возврата RequestClientAuthorization в своем модульном тесте, потому что это абстрактный класс. Вы также можете смоделировать вызов абстрактного метода AsActionResult для возврата некоторого ожидаемого смоделированного экземпляра, и вы будете утверждать в своем модульном тесте, что тестируемое действие контроллера возвращало этот ожидаемый результат действия.

1 голос
/ 18 января 2012

Если конструктор защищен, то производный тип может получить к нему доступ. Можете ли вы просто использовать Moq для создания макета OutgoingWebResponse (который внутренне заставит Moq извлечь из него и вызвать защищенный конструктор, я думаю) и вернуть его из вашей реализации метода mock?

Примерно так:

System.Net.HttpWebResponse mockResponse; // get this from somewhere
new Moq.Mock<DotNetOpenAuth.Messaging.OutgoingWebResponse>(mockResponse, 5);

Это должно позволить вам смоделировать OutgoingWebResponse. Следующая проблема возникает, где вы получаете экземпляр HttpWebResponse, поскольку он также имеет только защищенный конструктор. Вы можете продолжить цепочку и смоделировать это так же, как OutgoingWebResponse, и посмотреть, как далеко вы доберетесь.

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