我正在使用Moq框架编写单元测试,我有一个返回
的控制器函数return Json(new
{
redirectUrl = Url.Action("Action", "Controller"),
isredirection = true
});
我希望能够在redirectUrl
中测试结果,但不知道如何在Mock
中测试Url.Action.
,我如何设置,以便我可以指定Url.Action("Action", "Controller")
是否被称为返回这个?
你不能。关于模拟有一个很容易记住的规则——不能重写,不能模拟1。如果你是从Url
类派生的,你能重写Action
方法吗?不。也不能Moq, Rhino, FakeItEasy或任何其他基于DynamicProxy的框架。
您的选项缩小以下选项:
- 使用不同的框架,而不是基于DynamicProxy(这通常意味着基于编译器服务进行高级拦截)-这些工具通常是付费的。
- 用接口/委托包装有问题的调用,并将其注入测试代码(以便您可以使用免费框架模拟它)
包装会是什么样子?
public interface IUrlWrapper
{
string Action(string name, object values);
}
// Wrapper Interface
public class TestedClass
{
private readonly IUrlWrapper url;
public TestedClass(IUrlWrapper urlWrapper)
{
this.url = urlWrapper;
}
// ...
return Json(new
{
redirectUrl = this.url.Action("Action", "Controller"),
isredirection = true
});
// ...
}
有了这样的设置,您可以使用Moq,而不会出现进一步的问题。但是,在单个方法调用中,您也可以使用Func
委托,而不需要任何隔离框架:
// Func Delegate
public class TestedClass
{
private readonly Func<string, object, string> urlAction;
public TestedClass(Func<string, object, string> urlAction)
{
this.urlAction = urlAction;
}
// ...
return Json(new
{
redirectUrl = this.urlAction("Action", "Controller"),
isredirection = true
});
// ...
}
在您的测试中,您只需动态地创建委托。
1我写了一篇博客文章,详细介绍了这个问题:如何用…