1

我试图测试一个使用 DotNetOpenAuth 的 AccountController,但我遇到了问题。我想测试 Logon Actionresult 以查看它是否返回了正确的视图。测试失败是因为领域(我认为)有一个要求 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");
}

提前致谢,

泡菜

4

1 回答 1

2

如果控制器的依赖项之一要求 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 注入控制器,例如使用构造函数注入

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);

(此示例使用最小起订量。)

于 2010-03-04T09:31:11.787 回答