Test / Mock DotNetOpenAuth Контроллер - PullRequest
1 голос
/ 04 марта 2010

Я пытаюсь проверить AccountController, который использует DotNetOpenAuth, но столкнулся с проблемой. Я хочу проверить результат действия входа в систему и убедиться, что он возвращает правильные представления. Тест не пройден, поскольку область (я думаю) имеет контракт, который требует, чтобы HttpContext.Current не был нулевым Я думаю, что должен каким-то образом смоделировать запрос, но я не уверен, как мне это сделать.

Это код ActionResult. Он взят непосредственно из примера DotNetOpenAuth.

[AcceptVerbs(HttpVerbs.Post), ValidateAntiForgeryToken]
public ActionResult LogOn(string openid_identifier, 
                          bool rememberMe, 
                          string returnUrl)
{
    Identifier userSuppliedIdentifier;
    if (Identifier.TryParse(openid_identifier, out userSuppliedIdentifier))
    {
        try
        {
            var request = this.RelyingParty
                              .CreateRequest(openid_identifier,
                                             Realm.AutoDetect, 
                                             Url.ActionFull("LogOnReturnTo"));

            if (!string.IsNullOrEmpty(returnUrl))
            {
                request.SetUntrustedCallbackArgument("returnUrl", returnUrl);
            }
            return request.RedirectingResponse.AsActionResult();
        }
        catch (ProtocolException ex)
        {
            ModelState.AddModelError("OpenID", ex.Message);
        }
    }
    else
    {
        ModelState.AddModelError("openid_identifier", 
                                 "This doesn't look like a valid OpenID.");
    }
    return RedirectToAction("LogOn", "Account");
}

Заранее спасибо,

Pickels

1 Ответ

2 голосов
/ 04 марта 2010

Если для одной из зависимостей контроллера требуется, чтобы HttpContext.Current был доступен, вы не можете его напрямую смоделировать, но можете обернуть эту зависимость в саму тестируемую абстракцию.

Если мы предположим, что Realm является виновником, вы должны сначала извлечь интерфейс из него:

public interface IRealm
{
    // I don't know what the real AutoDetect property returns,
    // so I just assume bool
    bool AutoDetect { get; }
}

Вам, очевидно, потребуется реальная реализация IRealm:

public class RealmAdapter : IRealm
{
    bool AutoDetect { get { return Realm.AutoDetect; } }
}

Вы должны ввести абстрактный IRealm в контроллер, например, с помощью Конструктор Injection

public class MyController
{
    private readonly IRealm realm;

    public MyController(IRealm realm)
    {
        if( realm == null)
        {
            throw new ArgumentNullException("realm");
        }

        this.realm = realm;
    }
}

Теперь вы можете изменить реализацию метода LogOn, чтобы использовать this.realm вместо того, чтобы полагаться непосредственно на класс Realm.

Теперь модульное тестирование сможет предоставить фиктивный экземпляр IRealm для контроллера:

var realmMock = new Mock<IRealm>();
var sut = new MyController(realmMock.Object);

(В этом примере используется Moq.)

...