我尝试测试使用DotNetOpenAuth的AccountController,但我遇到了问题。我想测试Logon Actionresult,看它是否正在返回正确的视图。测试失败,因为领域(我认为)有一个合同,要求HttpContext.Current不为null。我想我必须以某种方式嘲笑这个请求,但我不确定我该怎么做。
这是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
答案 0 :(得分:2)
如果Controller的某个依赖项要求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);
(此示例使用Moq。)